@energycap/components 0.42.0 → 0.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/components.module.mjs +10 -5
- package/esm2022/lib/controls/calendar/calendar-item.component.mjs +46 -14
- package/esm2022/lib/controls/calendar/calendar.component.mjs +169 -121
- package/esm2022/lib/controls/calendar/calendar.types.mjs +2 -4
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/date-input-selection-strategy-base.mjs +57 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/day-selection-strategy.mjs +62 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/last-28-days-selection-strategy.mjs +100 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/last-7-days-selection-strategy.mjs +101 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/month-selection-strategy.mjs +76 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/quarter-selection-strategy.mjs +79 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/range-selection-strategy.mjs +210 -0
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/year-selection-strategy.mjs +81 -0
- package/esm2022/lib/controls/date-input/date-input.component.mjs +322 -113
- package/esm2022/lib/controls/date-input/date-input.types.mjs +44 -0
- package/esm2022/lib/controls/file-upload/file-upload.component.mjs +1 -1
- package/esm2022/lib/controls/form-control/form-control.component.mjs +6 -12
- package/esm2022/lib/core/date-time-helper.mjs +10 -2
- package/esm2022/lib/shared/directives/keyboard-nav-container/keyboard-nav-container.directive.mjs +100 -0
- package/esm2022/public-api.mjs +63 -61
- package/fesm2022/energycap-components.mjs +1666 -507
- package/fesm2022/energycap-components.mjs.map +1 -1
- package/lib/components.module.d.ts +9 -8
- package/lib/controls/calendar/calendar-item.component.d.ts +11 -6
- package/lib/controls/calendar/calendar.component.d.ts +21 -23
- package/lib/controls/calendar/calendar.types.d.ts +11 -7
- package/lib/controls/date-input/date-input-selection-strategies/date-input-selection-strategy-base.d.ts +42 -0
- package/lib/controls/date-input/date-input-selection-strategies/day-selection-strategy.d.ts +21 -0
- package/lib/controls/date-input/date-input-selection-strategies/last-28-days-selection-strategy.d.ts +21 -0
- package/lib/controls/date-input/date-input-selection-strategies/last-7-days-selection-strategy.d.ts +21 -0
- package/lib/controls/date-input/date-input-selection-strategies/month-selection-strategy.d.ts +18 -0
- package/lib/controls/date-input/date-input-selection-strategies/quarter-selection-strategy.d.ts +18 -0
- package/lib/controls/date-input/date-input-selection-strategies/range-selection-strategy.d.ts +21 -0
- package/lib/controls/date-input/date-input-selection-strategies/year-selection-strategy.d.ts +20 -0
- package/lib/controls/date-input/date-input.component.d.ts +63 -28
- package/lib/controls/date-input/date-input.types.d.ts +62 -0
- package/lib/controls/form-control/form-control.component.d.ts +4 -6
- package/lib/shared/directives/keyboard-nav-container/keyboard-nav-container.directive.d.ts +23 -0
- package/package.json +1 -1
- package/public-api.d.ts +62 -60
- package/src/assets/locales/en_US.json +9 -1
@@ -1,15 +1,15 @@
|
|
1
|
-
import * as
|
1
|
+
import * as i1$3 from '@angular/cdk/a11y';
|
2
2
|
import { A11yModule } from '@angular/cdk/a11y';
|
3
3
|
import * as i1$1 from '@angular/cdk/overlay';
|
4
4
|
import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
|
5
|
-
import * as i1$
|
5
|
+
import * as i1$4 from '@angular/cdk/scrolling';
|
6
6
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
7
7
|
import * as i1 from '@angular/common';
|
8
8
|
import { DOCUMENT, CommonModule } from '@angular/common';
|
9
9
|
import * as i0 from '@angular/core';
|
10
|
-
import { Injectable, EventEmitter, Component, HostBinding, Input, Output, ViewChild, Directive, Host,
|
10
|
+
import { Injectable, EventEmitter, Component, HostBinding, Input, Output, ViewChild, Directive, Host, Pipe, ChangeDetectionStrategy, HostListener, Inject, ViewEncapsulation, ContentChild, ElementRef, TemplateRef, ContentChildren, ViewContainerRef, NgModule, Injector } from '@angular/core';
|
11
11
|
import * as i4 from '@angular/forms';
|
12
|
-
import { Validators, UntypedFormControl, FormControlDirective, FormControl, UntypedFormGroup, UntypedFormArray,
|
12
|
+
import { Validators, UntypedFormControl, FormControlDirective, FormControl, FormGroup, UntypedFormGroup, UntypedFormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
13
13
|
import * as i1$2 from '@angular/router';
|
14
14
|
import { NavigationEnd, convertToParamMap, NavigationStart, Router, RouterModule, ActivatedRoute } from '@angular/router';
|
15
15
|
import * as i3 from '@ngx-translate/core';
|
@@ -455,65 +455,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
455
455
|
args: ['ecCopyTableButton']
|
456
456
|
}] } });
|
457
457
|
|
458
|
-
function isCalendarSelectionSingleDate(selection) {
|
459
|
-
return selection instanceof Date;
|
460
|
-
}
|
461
|
-
|
462
|
-
class CalendarItemComponent {
|
463
|
-
constructor() {
|
464
|
-
this.view = 'day';
|
465
|
-
this.today = false;
|
466
|
-
this.selected = false;
|
467
|
-
this.outsideActiveMonth = false;
|
468
|
-
}
|
469
|
-
ngOnChanges() {
|
470
|
-
if (this.view !== 'day') {
|
471
|
-
this.today = false;
|
472
|
-
this.outsideActiveMonth = false;
|
473
|
-
}
|
474
|
-
else {
|
475
|
-
this.today = moment(this.item?.date).isSame(moment(), 'day');
|
476
|
-
this.outsideActiveMonth = !moment(this.item?.date).isSame(this.activeDate, 'month');
|
477
|
-
}
|
478
|
-
this.selected = this.isSelected(this.item?.date, this.selection, this.view);
|
479
|
-
}
|
480
|
-
isSelected(date, selection, view) {
|
481
|
-
if (!date || !selection) {
|
482
|
-
return false;
|
483
|
-
}
|
484
|
-
if (isCalendarSelectionSingleDate(this.selection)) {
|
485
|
-
return moment(this.item?.date).isSame(this.selection, view);
|
486
|
-
}
|
487
|
-
else {
|
488
|
-
// TODO ECAP-26841: determine if the item is within the range selection
|
489
|
-
return false;
|
490
|
-
}
|
491
|
-
}
|
492
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
493
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CalendarItemComponent, selector: "button[ec-calendar-item]", inputs: { item: "item", activeDate: "activeDate", selection: "selection", view: "view" }, host: { properties: { "class.is-today": "this.today", "class.is-selected": "this.selected", "class.is-outside-active-month": "this.outsideActiveMonth" } }, usesOnChanges: true, ngImport: i0, template: '{{item?.label}}', isInline: true, styles: [":host{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;line-height:1.125rem}:host .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}:host .ec-icon{flex:none}:host .ec-icon+.label{flex:none;margin-left:.25rem}:host.has-badge{padding-right:.0625rem}:host:focus{outline:none;position:relative;z-index:1}:host:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}:host:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);opacity:1;--ec-color-icon: var(--ec-color-hint-dark)}:host:hover:not(:disabled){background-color:var(--ec-background-color-hover)}:host:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}:host:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}:host.is-selected,:host.is-selected:disabled{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-today{text-decoration:underline}:host.is-outside-active-month{color:var(--ec-color-hint-dark)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
494
|
-
}
|
495
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarItemComponent, decorators: [{
|
496
|
-
type: Component,
|
497
|
-
args: [{ selector: 'button[ec-calendar-item]', template: '{{item?.label}}', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;line-height:1.125rem}:host .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}:host .ec-icon{flex:none}:host .ec-icon+.label{flex:none;margin-left:.25rem}:host.has-badge{padding-right:.0625rem}:host:focus{outline:none;position:relative;z-index:1}:host:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}:host:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);opacity:1;--ec-color-icon: var(--ec-color-hint-dark)}:host:hover:not(:disabled){background-color:var(--ec-background-color-hover)}:host:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}:host:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}:host.is-selected,:host.is-selected:disabled{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-today{text-decoration:underline}:host.is-outside-active-month{color:var(--ec-color-hint-dark)}\n"] }]
|
498
|
-
}], ctorParameters: () => [], propDecorators: { item: [{
|
499
|
-
type: Input
|
500
|
-
}], activeDate: [{
|
501
|
-
type: Input
|
502
|
-
}], selection: [{
|
503
|
-
type: Input
|
504
|
-
}], view: [{
|
505
|
-
type: Input
|
506
|
-
}], today: [{
|
507
|
-
type: HostBinding,
|
508
|
-
args: ['class.is-today']
|
509
|
-
}], selected: [{
|
510
|
-
type: HostBinding,
|
511
|
-
args: ['class.is-selected']
|
512
|
-
}], outsideActiveMonth: [{
|
513
|
-
type: HostBinding,
|
514
|
-
args: ['class.is-outside-active-month']
|
515
|
-
}] } });
|
516
|
-
|
517
458
|
/**
|
518
459
|
* Helper class that provides common date constants and helpful date functions
|
519
460
|
*/
|
@@ -626,6 +567,8 @@ class DateTimeHelper {
|
|
626
567
|
* This is not an exhaustive list of formats, but it should cover most common formats.
|
627
568
|
*/
|
628
569
|
static { this.momentMedAndLongDateFormats = [
|
570
|
+
'DD MMM',
|
571
|
+
'MMM DD',
|
629
572
|
'DD MMM YY',
|
630
573
|
'DD MMM YYYY',
|
631
574
|
'DD MMMM YYYY',
|
@@ -633,7 +576,13 @@ class DateTimeHelper {
|
|
633
576
|
'MMM D, YYYY',
|
634
577
|
'MMM DD, YYYY',
|
635
578
|
'MMMM D, YYYY',
|
636
|
-
'MMMM DD, YYYY'
|
579
|
+
'MMMM DD, YYYY',
|
580
|
+
'MMM YY',
|
581
|
+
'MMM YYYY',
|
582
|
+
'MMMM YYYY',
|
583
|
+
'MMM, YY',
|
584
|
+
'MMM, YYYY',
|
585
|
+
'MMMM, YYYY',
|
637
586
|
]; }
|
638
587
|
/**
|
639
588
|
* Format to display the time portion of a datetime
|
@@ -733,257 +682,1169 @@ class DateTimeHelper {
|
|
733
682
|
}
|
734
683
|
}
|
735
684
|
|
685
|
+
/**
|
686
|
+
* Contains the logic for selecting, formatting, and parsing date dates for a specific selection mode.
|
687
|
+
*/
|
688
|
+
class DateInputSelectionStrategyBase {
|
689
|
+
/** Parses the string into a date using the provided parse formats. */
|
690
|
+
parseString(value, parseFormats, opts) {
|
691
|
+
if (!value) {
|
692
|
+
return null;
|
693
|
+
}
|
694
|
+
const date = moment(value, parseFormats);
|
695
|
+
if (date.isValid()) {
|
696
|
+
// If we're in a temporary state (when the user is typing in a textbox), we need to set the year to the current year if it's before the min year
|
697
|
+
// This prevents the calendars from showing unhelpful dates that are in the distant past before the user finishes typing in the date.
|
698
|
+
// We don't do this modification when the real selection happens on textbox blur.
|
699
|
+
if (opts?.shiftToCurrentYearIfBelow && date.isBefore(opts.shiftToCurrentYearIfBelow)) {
|
700
|
+
date.set('year', moment().year());
|
701
|
+
}
|
702
|
+
return date.toDate();
|
703
|
+
}
|
704
|
+
return null;
|
705
|
+
}
|
706
|
+
/** Returns a new selection for the provided date. */
|
707
|
+
getSelectionForQuickSelectDate(date, existingSelection) {
|
708
|
+
return this.getSelectionFromDate(date, existingSelection);
|
709
|
+
}
|
710
|
+
/** Returns the view for the primary calendar for the selection and selection mode */
|
711
|
+
getPrimaryCalendarView(selection, minDate, maxDate, currentView) {
|
712
|
+
let date;
|
713
|
+
// If we have a range, use the end date, defaulting to the start date or today
|
714
|
+
if (DateInput.isSelectionRange(selection)) {
|
715
|
+
date = selection.end || selection.start || new Date();
|
716
|
+
// If we have a single date, use it, defaulting to today
|
717
|
+
}
|
718
|
+
else {
|
719
|
+
date = selection || new Date();
|
720
|
+
}
|
721
|
+
// Ensure the date is within the min and max dates
|
722
|
+
date = date < minDate ? minDate : date;
|
723
|
+
date = date > maxDate ? maxDate : date;
|
724
|
+
// If the current calendar view mode is valid for the selection mode, use it, otherwise use the selection view mode
|
725
|
+
// This prevents the calendar from changing view modes as the user types/blurs the textboxes as long as the view mode is valid
|
726
|
+
const viewMode = this.validViewModes.includes(currentView.mode) ? currentView.mode : this.selectionViewMode;
|
727
|
+
return { mode: viewMode, date };
|
728
|
+
}
|
729
|
+
;
|
730
|
+
/**
|
731
|
+
* Returns the view for the secondary calendar for the selection and selection mode.
|
732
|
+
* This is is only used by the range selection strategy. All others just return the current date.
|
733
|
+
*/
|
734
|
+
getSecondaryCalendarView(selection, minDate, maxDate, currentView) {
|
735
|
+
return { mode: this.selectionViewMode, date: new Date() };
|
736
|
+
}
|
737
|
+
;
|
738
|
+
}
|
739
|
+
|
740
|
+
/**
|
741
|
+
* Selection strategy for the 'day' selection mode.
|
742
|
+
*/
|
743
|
+
class DaySelectionStrategy extends DateInputSelectionStrategyBase {
|
744
|
+
constructor(dateDisplayPipe) {
|
745
|
+
super();
|
746
|
+
this.dateDisplayPipe = dateDisplayPipe;
|
747
|
+
this.selectionViewMode = 'day';
|
748
|
+
this.validViewModes = ['day', 'month', 'year'];
|
749
|
+
this.showSecondaryTextbox = false;
|
750
|
+
this.showSecondaryCalendar = false;
|
751
|
+
}
|
752
|
+
formatSelection(selection) {
|
753
|
+
// If the selection is a single date, format it into the first textbox.
|
754
|
+
if (DateInput.isSelectionSingleDate(selection)) {
|
755
|
+
return { textbox: this.dateDisplayPipe.transform(selection, true), textbox2: null };
|
756
|
+
// Otherwise, clear both textboxes. This shouldn't happen based on current date input flows,
|
757
|
+
// and even if it did there's not really a good way to handle it.
|
758
|
+
}
|
759
|
+
else {
|
760
|
+
return { textbox: null, textbox2: null };
|
761
|
+
}
|
762
|
+
}
|
763
|
+
parseTextboxValues(value, parseFormats, opts) {
|
764
|
+
return this.parseString(value.textbox, parseFormats, opts);
|
765
|
+
}
|
766
|
+
getSelectionFromDate(date) {
|
767
|
+
// Nice and simple
|
768
|
+
return date;
|
769
|
+
}
|
770
|
+
getNewSelectionFromExisting(previousSelection) {
|
771
|
+
// If the previous selection was a range, return the end date and default to the start date if there isn't one.
|
772
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
773
|
+
return previousSelection.end || previousSelection.start;
|
774
|
+
// If the previous selection was a single date, return it.
|
775
|
+
}
|
776
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
777
|
+
return previousSelection;
|
778
|
+
}
|
779
|
+
return null;
|
780
|
+
}
|
781
|
+
getNextSelection(selection) {
|
782
|
+
// Add a single day to the selection
|
783
|
+
if (DateInput.isSelectionSingleDate(selection)) {
|
784
|
+
return moment(selection).add(1, 'day').toDate();
|
785
|
+
}
|
786
|
+
// This shouldn't happen based on current date input flows, but if it does just return the selection as-is.
|
787
|
+
return selection;
|
788
|
+
}
|
789
|
+
getPreviousSelection(selection) {
|
790
|
+
// Subtract a single day from the selection
|
791
|
+
if (DateInput.isSelectionSingleDate(selection)) {
|
792
|
+
return moment(selection).subtract(1, 'day').toDate();
|
793
|
+
}
|
794
|
+
// This shouldn't happen based on current date input flows, but if it does just return the selection as-is.
|
795
|
+
return selection;
|
796
|
+
}
|
797
|
+
}
|
798
|
+
|
799
|
+
/**
|
800
|
+
* Selection strategy for the 'last 28 days' selection mode.
|
801
|
+
*/
|
802
|
+
class Last28DaysSelectionStrategy extends DateInputSelectionStrategyBase {
|
803
|
+
constructor(rangeStrategy) {
|
804
|
+
super();
|
805
|
+
this.rangeStrategy = rangeStrategy;
|
806
|
+
this.selectionViewMode = 'day';
|
807
|
+
this.validViewModes = ['day', 'month', 'year'];
|
808
|
+
this.showSecondaryTextbox = true;
|
809
|
+
this.showSecondaryCalendar = false;
|
810
|
+
}
|
811
|
+
formatSelection(value) {
|
812
|
+
// Delegate to the range strategy for formatting since the logic is the same
|
813
|
+
return this.rangeStrategy.formatSelection(value);
|
814
|
+
}
|
815
|
+
parseTextboxValues(value, parseFormats, opts) {
|
816
|
+
let start = this.parseString(value.textbox, parseFormats, opts);
|
817
|
+
let end = this.parseString(value.textbox2, parseFormats, opts);
|
818
|
+
if (start && end) {
|
819
|
+
// Even if both dates are provided, it's possible that they don't match a 28-day range
|
820
|
+
// Update the start and end dates to match a 28-day range, keying off the end date if parseFromEnd is true
|
821
|
+
// parseFromEnd is true when a date is being entered from the end date textbox
|
822
|
+
if (opts?.parseFromEnd) {
|
823
|
+
start = moment(end).subtract(27, 'days').toDate();
|
824
|
+
}
|
825
|
+
else {
|
826
|
+
end = moment(start).add(27, 'days').toDate();
|
827
|
+
}
|
828
|
+
}
|
829
|
+
// If the start date is not provided, we'll use the end date to calculate the start date
|
830
|
+
if (!start && end && !opts?.preventAutoComplete) {
|
831
|
+
start = moment(end).subtract(27, 'days').toDate();
|
832
|
+
}
|
833
|
+
// If the end date is not provided, we'll use the start date to calculate the end date
|
834
|
+
if (!end && start && !opts?.preventAutoComplete) {
|
835
|
+
end = moment(start).add(27, 'days').toDate();
|
836
|
+
}
|
837
|
+
if (!start && !end) {
|
838
|
+
return null;
|
839
|
+
}
|
840
|
+
else {
|
841
|
+
return { start, end };
|
842
|
+
}
|
843
|
+
}
|
844
|
+
getSelectionFromDate(date) {
|
845
|
+
return {
|
846
|
+
start: moment(date).subtract(27, 'days').toDate(),
|
847
|
+
end: date
|
848
|
+
};
|
849
|
+
}
|
850
|
+
getNewSelectionFromExisting(previousSelection) {
|
851
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
852
|
+
// If the range only has a start date, make the 28-day range start on that date
|
853
|
+
if (!previousSelection.end && previousSelection.start) {
|
854
|
+
return {
|
855
|
+
start: previousSelection.start,
|
856
|
+
end: moment(previousSelection.start).add(27, 'days').toDate()
|
857
|
+
};
|
858
|
+
// If the range only has an end date, make the 28-day range end on that date
|
859
|
+
}
|
860
|
+
else if (previousSelection.end) {
|
861
|
+
return this.getSelectionFromDate(previousSelection.end);
|
862
|
+
}
|
863
|
+
// If the previous selection was a single date, make the range the 28 days ending on that date
|
864
|
+
}
|
865
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
866
|
+
return this.getSelectionFromDate(previousSelection);
|
867
|
+
}
|
868
|
+
return null;
|
869
|
+
}
|
870
|
+
getNextSelection(selection) {
|
871
|
+
// Move the selection to the next 28 days
|
872
|
+
if (DateInput.isSelectionRange(selection) && selection.end) {
|
873
|
+
return {
|
874
|
+
start: moment(selection.end).add(1, 'day').toDate(),
|
875
|
+
end: moment(selection.end).add(28, 'days').toDate()
|
876
|
+
};
|
877
|
+
}
|
878
|
+
// This shouldn't happen since the next stepper is disabled if the selection only has one date.
|
879
|
+
// Just return the selection as-is in this case.
|
880
|
+
return selection;
|
881
|
+
}
|
882
|
+
getPreviousSelection(selection) {
|
883
|
+
// Move the selection to the previous 28 days
|
884
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
885
|
+
return {
|
886
|
+
start: moment(selection.start).subtract(28, 'days').toDate(),
|
887
|
+
end: moment(selection.start).subtract(1, 'day').toDate()
|
888
|
+
};
|
889
|
+
}
|
890
|
+
// This shouldn't happen since the previous stepper is disabled if the selection only has one date.
|
891
|
+
// Just return the selection as-is in this case.
|
892
|
+
return selection;
|
893
|
+
}
|
894
|
+
}
|
895
|
+
|
896
|
+
/**
|
897
|
+
* Selection strategy for the 'last 7 days' selection mode.
|
898
|
+
*/
|
899
|
+
class Last7DaysSelectionStrategy extends DateInputSelectionStrategyBase {
|
900
|
+
constructor(rangeStrategy) {
|
901
|
+
super();
|
902
|
+
this.rangeStrategy = rangeStrategy;
|
903
|
+
this.selectionViewMode = 'day';
|
904
|
+
this.validViewModes = ['day', 'month', 'year'];
|
905
|
+
this.showSecondaryTextbox = true;
|
906
|
+
this.showSecondaryCalendar = false;
|
907
|
+
}
|
908
|
+
formatSelection(value) {
|
909
|
+
// Delegate to the range strategy for formatting since the logic is the same
|
910
|
+
return this.rangeStrategy.formatSelection(value);
|
911
|
+
}
|
912
|
+
parseTextboxValues(value, parseFormats, opts) {
|
913
|
+
let start = this.parseString(value.textbox, parseFormats, opts);
|
914
|
+
let end = this.parseString(value.textbox2, parseFormats, opts);
|
915
|
+
if (start && end) {
|
916
|
+
// Even if both dates are provided, it's possible that they don't match a 7-day range
|
917
|
+
// Update the start and end dates to match a 7-day range, keying off the end date if parseFromEnd is true
|
918
|
+
// parseFromEnd is true when a date is being entered from the end date textbox
|
919
|
+
if (opts?.parseFromEnd) {
|
920
|
+
start = moment(end).subtract(6, 'days').toDate();
|
921
|
+
}
|
922
|
+
else {
|
923
|
+
end = moment(start).add(6, 'days').toDate();
|
924
|
+
}
|
925
|
+
}
|
926
|
+
// If the start date is not provided, we'll use the end date to calculate the start date
|
927
|
+
if (!start && end && !opts?.preventAutoComplete) {
|
928
|
+
start = moment(end).subtract(6, 'days').toDate();
|
929
|
+
}
|
930
|
+
// If the end date is not provided, we'll use the start date to calculate the end date
|
931
|
+
if (!end && start && !opts?.preventAutoComplete) {
|
932
|
+
end = moment(start).add(6, 'days').toDate();
|
933
|
+
}
|
934
|
+
if (!start && !end) {
|
935
|
+
return null;
|
936
|
+
}
|
937
|
+
else {
|
938
|
+
return { start, end };
|
939
|
+
}
|
940
|
+
}
|
941
|
+
getSelectionFromDate(date) {
|
942
|
+
// Base the selection on the given date, moving back 6 days
|
943
|
+
return {
|
944
|
+
start: moment(date).subtract(6, 'days').toDate(),
|
945
|
+
end: date
|
946
|
+
};
|
947
|
+
}
|
948
|
+
getNewSelectionFromExisting(previousSelection) {
|
949
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
950
|
+
// If we don't have an end date, create the new selection based on the start date forwards
|
951
|
+
if (!previousSelection.end && previousSelection.start) {
|
952
|
+
return {
|
953
|
+
start: previousSelection.start,
|
954
|
+
end: moment(previousSelection.start).add(6, 'days').toDate()
|
955
|
+
};
|
956
|
+
// Otherwise, create the new selection based on the end date backwards
|
957
|
+
}
|
958
|
+
else if (previousSelection.end) {
|
959
|
+
return this.getSelectionFromDate(previousSelection.end);
|
960
|
+
}
|
961
|
+
// If we only have a single date, create the new selection based on that date backwards
|
962
|
+
}
|
963
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
964
|
+
return this.getSelectionFromDate(previousSelection);
|
965
|
+
}
|
966
|
+
return null;
|
967
|
+
}
|
968
|
+
getNextSelection(selection) {
|
969
|
+
// Shift the range forward by 7 days
|
970
|
+
if (DateInput.isSelectionRange(selection) && selection.end) {
|
971
|
+
return {
|
972
|
+
start: moment(selection.end).add(1, 'day').toDate(),
|
973
|
+
end: moment(selection.end).add(7, 'days').toDate()
|
974
|
+
};
|
975
|
+
}
|
976
|
+
// This shouldn't happen since the next stepper is disabled if the selection only has one date.
|
977
|
+
// Just return the selection as-is in this case.
|
978
|
+
return selection;
|
979
|
+
}
|
980
|
+
getPreviousSelection(selection) {
|
981
|
+
// Shift the range back 7 days
|
982
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
983
|
+
return {
|
984
|
+
start: moment(selection.start).subtract(7, 'days').toDate(),
|
985
|
+
end: moment(selection.start).subtract(1, 'day').toDate()
|
986
|
+
};
|
987
|
+
}
|
988
|
+
// This shouldn't happen since the previous stepper is disabled if the selection only has one date.
|
989
|
+
// Just return the selection as-is in this case.
|
990
|
+
return selection;
|
991
|
+
}
|
992
|
+
}
|
993
|
+
|
994
|
+
/**
|
995
|
+
* Selection strategy for the 'month' selection mode.
|
996
|
+
*/
|
997
|
+
class MonthSelectionStrategy extends DateInputSelectionStrategyBase {
|
998
|
+
constructor() {
|
999
|
+
super(...arguments);
|
1000
|
+
this.selectionViewMode = 'month';
|
1001
|
+
this.validViewModes = ['month', 'year'];
|
1002
|
+
this.showSecondaryTextbox = false;
|
1003
|
+
this.showSecondaryCalendar = false;
|
1004
|
+
}
|
1005
|
+
formatSelection(selection) {
|
1006
|
+
if (!selection) {
|
1007
|
+
return { textbox: null, textbox2: null };
|
1008
|
+
}
|
1009
|
+
// We only need one date in the range to format since it only spans one month
|
1010
|
+
// A single date selection shouldn't happen in this mode but it's simple enough to handle
|
1011
|
+
const date = DateInput.isSelectionRange(selection) ? selection.start : selection;
|
1012
|
+
return {
|
1013
|
+
textbox: moment(date).format('MMM, YYYY'),
|
1014
|
+
textbox2: null
|
1015
|
+
};
|
1016
|
+
}
|
1017
|
+
parseTextboxValues(value, parseFormats, opts) {
|
1018
|
+
// Only one textbox is used in this mode
|
1019
|
+
const date = this.parseString(value.textbox, parseFormats, opts);
|
1020
|
+
if (!date) {
|
1021
|
+
return null;
|
1022
|
+
}
|
1023
|
+
return this.getSelectionFromDate(date);
|
1024
|
+
}
|
1025
|
+
getSelectionFromDate(date) {
|
1026
|
+
return {
|
1027
|
+
start: moment(date).startOf('month').toDate(),
|
1028
|
+
end: moment(date).endOf('month').toDate()
|
1029
|
+
};
|
1030
|
+
}
|
1031
|
+
getNewSelectionFromExisting(previousSelection) {
|
1032
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
1033
|
+
// We'll use the existing selection's end date and fall back to the start date if it's not available
|
1034
|
+
const date = previousSelection.end || previousSelection.start;
|
1035
|
+
if (date) {
|
1036
|
+
return this.getSelectionFromDate(date);
|
1037
|
+
}
|
1038
|
+
}
|
1039
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
1040
|
+
// If the previous selection was a single date, make the range that month
|
1041
|
+
return this.getSelectionFromDate(previousSelection);
|
1042
|
+
}
|
1043
|
+
return null;
|
1044
|
+
}
|
1045
|
+
getNextSelection(selection) {
|
1046
|
+
// Move the selection to the next month
|
1047
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
1048
|
+
const date = moment(selection.start).add(1, 'month');
|
1049
|
+
return this.getSelectionFromDate(date.toDate());
|
1050
|
+
}
|
1051
|
+
// This shouldn't happen since the next stepper is disabled if the selection only has one date.
|
1052
|
+
// If it does, just return the selection as-is.
|
1053
|
+
return selection;
|
1054
|
+
}
|
1055
|
+
getPreviousSelection(selection) {
|
1056
|
+
// Move the selection to the previous month
|
1057
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
1058
|
+
const date = moment(selection.start).subtract(1, 'month');
|
1059
|
+
return this.getSelectionFromDate(date.toDate());
|
1060
|
+
}
|
1061
|
+
// This shouldn't happen since the previous stepper is disabled if the selection only has one date.
|
1062
|
+
// If it does, just return the selection as-is.
|
1063
|
+
return selection;
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
/**
|
1068
|
+
* Selection strategy for the 'month' selection mode.
|
1069
|
+
*/
|
1070
|
+
class QuarterSelectionStrategy extends DateInputSelectionStrategyBase {
|
1071
|
+
constructor() {
|
1072
|
+
super(...arguments);
|
1073
|
+
this.selectionViewMode = 'quarter';
|
1074
|
+
this.validViewModes = ['quarter', 'year'];
|
1075
|
+
this.showSecondaryTextbox = false;
|
1076
|
+
this.showSecondaryCalendar = false;
|
1077
|
+
}
|
1078
|
+
formatSelection(selection) {
|
1079
|
+
// Format the the quarter range as "MMM–MMM, YYYY"
|
1080
|
+
// We only have one textbox in this mode
|
1081
|
+
if (DateInput.isSelectionRange(selection)) {
|
1082
|
+
const start = moment(selection.start).format('MMM');
|
1083
|
+
const end = moment(selection.end).format('MMM');
|
1084
|
+
const year = moment(selection.end).format('YYYY');
|
1085
|
+
return {
|
1086
|
+
textbox: `${start}–${end}, ${year}`,
|
1087
|
+
textbox2: null
|
1088
|
+
};
|
1089
|
+
}
|
1090
|
+
// This shouldn't happen since the selection should always be a range in quarter mode
|
1091
|
+
return { textbox: null, textbox2: null };
|
1092
|
+
}
|
1093
|
+
parseTextboxValues(value, parseFormats, opts) {
|
1094
|
+
// Only one textbox is used in this mode
|
1095
|
+
const date = this.parseString(value.textbox, parseFormats, opts);
|
1096
|
+
if (!date) {
|
1097
|
+
return null;
|
1098
|
+
}
|
1099
|
+
return this.getSelectionFromDate(date);
|
1100
|
+
}
|
1101
|
+
getSelectionFromDate(date) {
|
1102
|
+
return {
|
1103
|
+
start: moment(date).startOf('quarter').toDate(),
|
1104
|
+
end: moment(date).endOf('quarter').toDate()
|
1105
|
+
};
|
1106
|
+
}
|
1107
|
+
getNewSelectionFromExisting(previousSelection) {
|
1108
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
1109
|
+
// Base the quarter range off of the existing selection's end date, falling back to the start date
|
1110
|
+
const date = previousSelection.end || previousSelection.start;
|
1111
|
+
if (date) {
|
1112
|
+
return this.getSelectionFromDate(date);
|
1113
|
+
}
|
1114
|
+
}
|
1115
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
1116
|
+
// If the previous selection was a single date, make the range that quarter
|
1117
|
+
return this.getSelectionFromDate(previousSelection);
|
1118
|
+
}
|
1119
|
+
return null;
|
1120
|
+
}
|
1121
|
+
getNextSelection(selection) {
|
1122
|
+
// Move the selection to the next quarter
|
1123
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
1124
|
+
const date = moment(selection.start).add(1, 'quarter');
|
1125
|
+
return this.getSelectionFromDate(date.toDate());
|
1126
|
+
}
|
1127
|
+
// This shouldn't happen since the next stepper is disabled if the selection only has one date.
|
1128
|
+
// If it does, just return the selection as-is.
|
1129
|
+
return selection;
|
1130
|
+
}
|
1131
|
+
getPreviousSelection(selection) {
|
1132
|
+
// Move the selection to the previous quarter
|
1133
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
1134
|
+
const date = moment(selection.start).subtract(1, 'quarter');
|
1135
|
+
return this.getSelectionFromDate(date.toDate());
|
1136
|
+
}
|
1137
|
+
// This shouldn't happen since the previous stepper is disabled if the selection only has one date.
|
1138
|
+
// If it does, just return the selection as-is.
|
1139
|
+
return selection;
|
1140
|
+
}
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
/**
|
1144
|
+
* Selection strategy for the 'range' selection mode.
|
1145
|
+
*/
|
1146
|
+
class RangeSelectionStrategy extends DateInputSelectionStrategyBase {
|
1147
|
+
constructor() {
|
1148
|
+
super(...arguments);
|
1149
|
+
this.selectionViewMode = 'day';
|
1150
|
+
this.validViewModes = ['day', 'month', 'year'];
|
1151
|
+
this.showSecondaryTextbox = true;
|
1152
|
+
this.showSecondaryCalendar = true;
|
1153
|
+
}
|
1154
|
+
formatSelection(selection) {
|
1155
|
+
if (!selection) {
|
1156
|
+
return { textbox: null, textbox2: null };
|
1157
|
+
}
|
1158
|
+
// We use the 'll' moment medium format here to make sure the formatted date is formatted according to the user's locale
|
1159
|
+
if (DateInput.isSelectionSingleDate(selection)) {
|
1160
|
+
return { textbox: moment(selection).format('ll'), textbox2: null };
|
1161
|
+
}
|
1162
|
+
else {
|
1163
|
+
const start = selection.start ? moment(selection.start).format('ll') : null;
|
1164
|
+
const end = selection.end ? moment(selection.end).format('ll') : null;
|
1165
|
+
return { textbox: start, textbox2: end };
|
1166
|
+
}
|
1167
|
+
}
|
1168
|
+
parseTextboxValues(value, parseFormats, opts) {
|
1169
|
+
let start = this.parseString(value.textbox, parseFormats, opts);
|
1170
|
+
let end = this.parseString(value.textbox2, parseFormats, opts);
|
1171
|
+
// If the start date is after the end date, we need to clear out the invalid date. This is different from the last 7/28 days strategies
|
1172
|
+
// because we don't have a fixed range to automatically adjust the dates to. If the user is changing the begin date or end date and ends
|
1173
|
+
// up crossing the other date, we should clear out the date that's not being changed so that the user can enter a valid range using the
|
1174
|
+
// begin/end date they just entered.
|
1175
|
+
if (start && end && moment(start).isAfter(end)) {
|
1176
|
+
if (opts?.parseFromEnd) {
|
1177
|
+
start = null;
|
1178
|
+
}
|
1179
|
+
else {
|
1180
|
+
end = null;
|
1181
|
+
}
|
1182
|
+
}
|
1183
|
+
if (!start && !end) {
|
1184
|
+
return null;
|
1185
|
+
}
|
1186
|
+
else {
|
1187
|
+
return { start, end };
|
1188
|
+
}
|
1189
|
+
}
|
1190
|
+
getSelectionFromDate(date, existingSelection) {
|
1191
|
+
if (DateInput.isSelectionRange(existingSelection)) {
|
1192
|
+
const { start, end } = existingSelection;
|
1193
|
+
if (start && !end) {
|
1194
|
+
// If the selected date is before the existing start date, set it as the new start date and use the existing start date as the end date
|
1195
|
+
return moment(date).isBefore(start) ? { start: date, end: start } : { start, end: date };
|
1196
|
+
}
|
1197
|
+
if (end && !start) {
|
1198
|
+
// If the selected date is after the existing end date, set it as the new end date and use the existing end date as the start date
|
1199
|
+
return moment(date).isBefore(end) ? { start: date, end } : { start: end, end: date };
|
1200
|
+
}
|
1201
|
+
}
|
1202
|
+
else if (DateInput.isSelectionSingleDate(existingSelection)) {
|
1203
|
+
// If the selected date is before the existing date, set it as the new start date and use the existing date as the end date
|
1204
|
+
return moment(date).isBefore(existingSelection) ? { start: date, end: existingSelection } : { start: existingSelection, end: date };
|
1205
|
+
}
|
1206
|
+
// If no selection exists or we already have a complete selection, start a new one with the selected date as the start date.
|
1207
|
+
return { start: date, end: null };
|
1208
|
+
}
|
1209
|
+
getNewSelectionFromExisting(previousSelection) {
|
1210
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
1211
|
+
// If we have a range, just return it as is. We don't have a fixed range to adjust the dates to.
|
1212
|
+
// Even if it's incomplete, the user will still be able to select the remaining date.
|
1213
|
+
return previousSelection;
|
1214
|
+
}
|
1215
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
1216
|
+
// If we have a single date selection, use it as the start date for the new one.
|
1217
|
+
return { start: previousSelection, end: null };
|
1218
|
+
}
|
1219
|
+
return null;
|
1220
|
+
}
|
1221
|
+
getSelectionForQuickSelectDate(date, existingSelection) {
|
1222
|
+
// If we have a valid range, we'll shift the range to the date provided, using it as the end date
|
1223
|
+
// The new selection will have the same length as the previous.
|
1224
|
+
if (DateInput.isSelectionRange(existingSelection) && existingSelection.start && existingSelection.end) {
|
1225
|
+
const length = moment(existingSelection.end).diff(existingSelection.start, 'days');
|
1226
|
+
return {
|
1227
|
+
start: moment(date).subtract(length, 'days').toDate(),
|
1228
|
+
end: date
|
1229
|
+
};
|
1230
|
+
}
|
1231
|
+
// If we only have a single date, we'll use the date provided as the end date.
|
1232
|
+
// The user will be able to select the start date.
|
1233
|
+
return { start: null, end: date };
|
1234
|
+
}
|
1235
|
+
getNextSelection(selection) {
|
1236
|
+
// We can only determine the next selection if we have a valid range
|
1237
|
+
if (DateInput.isSelectionRange(selection) && selection.start && selection.end) {
|
1238
|
+
// Shift the range forward by the number of days between the start and end dates
|
1239
|
+
const length = moment(selection.end).diff(selection.start, 'days');
|
1240
|
+
return {
|
1241
|
+
start: moment(selection.end).add(1, 'days').toDate(),
|
1242
|
+
end: moment(selection.end).add(1 + length, 'days').toDate()
|
1243
|
+
};
|
1244
|
+
}
|
1245
|
+
// This shouldn't happen since the next stepper is disabled if the selection only has one date.
|
1246
|
+
// If it does, just return the selection as-is.
|
1247
|
+
return selection;
|
1248
|
+
}
|
1249
|
+
getPreviousSelection(selection) {
|
1250
|
+
// We can only determine the previous selection if we have a valid range
|
1251
|
+
if (DateInput.isSelectionRange(selection) && selection.start && selection.end) {
|
1252
|
+
// Shift the range back by the number of days between the start and end dates
|
1253
|
+
const length = moment(selection.end).diff(selection.start, 'days');
|
1254
|
+
return {
|
1255
|
+
start: moment(selection.start).subtract(1 + length, 'days').toDate(),
|
1256
|
+
end: moment(selection.start).subtract(1, 'days').toDate()
|
1257
|
+
};
|
1258
|
+
}
|
1259
|
+
// This shouldn't happen since the previous stepper is disabled if the selection only has one date.
|
1260
|
+
// If it does, just return the selection as-is.
|
1261
|
+
return selection;
|
1262
|
+
}
|
1263
|
+
getPrimaryCalendarView(selection, minDate, maxDate, currentView) {
|
1264
|
+
let viewDate;
|
1265
|
+
if (DateInput.isSelectionRange(selection)) {
|
1266
|
+
let start = selection.start ? moment(selection.start) : null;
|
1267
|
+
let end = selection.end ? moment(selection.end) : null;
|
1268
|
+
// Since we're in range mode, the primary calendar is mostly concerned with the start date
|
1269
|
+
if (start) {
|
1270
|
+
// If we have a start date in the selection and it's before the min date, shift the view to the min date.
|
1271
|
+
if (start.isBefore(minDate, 'month')) {
|
1272
|
+
viewDate = minDate;
|
1273
|
+
// If the start is after the max date, shift the view to the max date.
|
1274
|
+
}
|
1275
|
+
else if (start.isSameOrAfter(maxDate, 'month')) {
|
1276
|
+
// the secondary calendar will show the max date month.
|
1277
|
+
// The primary calendar will show the month before the max date.
|
1278
|
+
viewDate = moment(maxDate).subtract(1, 'month').toDate();
|
1279
|
+
}
|
1280
|
+
else {
|
1281
|
+
viewDate = start.toDate();
|
1282
|
+
}
|
1283
|
+
}
|
1284
|
+
else if (end && end.isSameOrBefore(minDate, 'month')) {
|
1285
|
+
// If we don't have a start date, and the end date is the same month or before the min date, shift the view to the min date.
|
1286
|
+
viewDate = minDate;
|
1287
|
+
}
|
1288
|
+
else if (end && end.isSameOrBefore(new Date(), 'month')) {
|
1289
|
+
// If we don't have a start date, and the end date is the same month or before the current month, shift the view to the month before the end
|
1290
|
+
viewDate = moment(end).subtract(1, 'month').toDate();
|
1291
|
+
}
|
1292
|
+
else {
|
1293
|
+
// Otherwise, show the current month.
|
1294
|
+
viewDate = new Date();
|
1295
|
+
}
|
1296
|
+
}
|
1297
|
+
else {
|
1298
|
+
viewDate = selection || new Date();
|
1299
|
+
}
|
1300
|
+
// If the current calendar view mode is valid for the selection mode, use it, otherwise use the selection view mode
|
1301
|
+
// This prevents the calendar from changing view modes as the user types/blurs the textboxes as long as the view mode is valid
|
1302
|
+
const viewMode = this.validViewModes.includes(currentView.mode) ? currentView.mode : this.selectionViewMode;
|
1303
|
+
return { mode: viewMode, date: viewDate };
|
1304
|
+
}
|
1305
|
+
getSecondaryCalendarView(selection, minDate, maxDate, currentView) {
|
1306
|
+
let viewDate;
|
1307
|
+
if (DateInput.isSelectionRange(selection)) {
|
1308
|
+
let start = selection.start ? moment(selection.start) : null;
|
1309
|
+
let end = selection.end ? moment(selection.end) : null;
|
1310
|
+
// The secondary calendar is primarily concerned with the end date in the selection.
|
1311
|
+
if (end) {
|
1312
|
+
if (end.isAfter(maxDate, 'month')) {
|
1313
|
+
// If the end date is after the max date, shift the view to the max date.
|
1314
|
+
viewDate = maxDate;
|
1315
|
+
}
|
1316
|
+
else if (end.isSameOrBefore(minDate, 'month')) {
|
1317
|
+
// If the end date is the same month or before the min date, shift the view to show
|
1318
|
+
// the month after the min date. The primary calendar will show the min date month.
|
1319
|
+
viewDate = moment(minDate).add(1, 'month').toDate();
|
1320
|
+
}
|
1321
|
+
else {
|
1322
|
+
// Otherwise, show the end date month.
|
1323
|
+
viewDate = end.toDate();
|
1324
|
+
}
|
1325
|
+
}
|
1326
|
+
else if (start && start.isSameOrAfter(maxDate, 'month')) {
|
1327
|
+
// If we don't have an end date, and the start date is after the max date, show the max date month
|
1328
|
+
viewDate = maxDate;
|
1329
|
+
}
|
1330
|
+
else if (start && start.isSameOrAfter(new Date(), 'month')) {
|
1331
|
+
// If we don't have an end date, and the start date is on or after the current month,
|
1332
|
+
// show the month after the start date.
|
1333
|
+
viewDate = moment(start).add(1, 'month').toDate();
|
1334
|
+
}
|
1335
|
+
else {
|
1336
|
+
// Otherwise, show the current month.
|
1337
|
+
viewDate = new Date();
|
1338
|
+
}
|
1339
|
+
}
|
1340
|
+
else {
|
1341
|
+
viewDate = selection || new Date();
|
1342
|
+
}
|
1343
|
+
// If the current calendar view mode is valid for the selection mode, use it, otherwise use the selection view mode
|
1344
|
+
// This prevents the calendar from changing view modes as the user types/blurs the textboxes as long as the view mode is valid
|
1345
|
+
const viewMode = this.validViewModes.includes(currentView.mode) ? currentView.mode : this.selectionViewMode;
|
1346
|
+
return { mode: viewMode, date: viewDate };
|
1347
|
+
}
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
/**
|
1351
|
+
* Selection strategy for the 'year' selection mode.
|
1352
|
+
*/
|
1353
|
+
class YearSelectionStrategy extends DateInputSelectionStrategyBase {
|
1354
|
+
constructor() {
|
1355
|
+
super(...arguments);
|
1356
|
+
this.selectionViewMode = 'year';
|
1357
|
+
this.validViewModes = ['year'];
|
1358
|
+
this.showSecondaryTextbox = false;
|
1359
|
+
this.showSecondaryCalendar = false;
|
1360
|
+
}
|
1361
|
+
formatSelection(selection) {
|
1362
|
+
if (!selection) {
|
1363
|
+
return { textbox: null, textbox2: null };
|
1364
|
+
}
|
1365
|
+
// Only one date is needed for formatting since the ranges span a single year.
|
1366
|
+
// There shouldn't be any case where there's only a single date but it's covered anyway.
|
1367
|
+
const date = DateInput.isSelectionRange(selection) ? selection.start : selection;
|
1368
|
+
return { textbox: moment(date).format('YYYY'), textbox2: null };
|
1369
|
+
}
|
1370
|
+
parseString(value, parseFormats, opts) {
|
1371
|
+
// Including 'YY' and 'YYYY' as valid formats for year input. These aren't included in the default parse
|
1372
|
+
// formats because they cause issues with the default date parsing.
|
1373
|
+
return super.parseString(value, ['YY', 'YYYY', ...parseFormats], opts);
|
1374
|
+
}
|
1375
|
+
parseTextboxValues(value, parseFormats, opts) {
|
1376
|
+
// Only a single textbox is used in year mode
|
1377
|
+
const date = this.parseString(value.textbox, parseFormats, opts);
|
1378
|
+
if (!date) {
|
1379
|
+
return null;
|
1380
|
+
}
|
1381
|
+
return this.getSelectionFromDate(date);
|
1382
|
+
}
|
1383
|
+
getSelectionFromDate(date) {
|
1384
|
+
return {
|
1385
|
+
start: moment(date).startOf('year').toDate(),
|
1386
|
+
end: moment(date).endOf('year').toDate()
|
1387
|
+
};
|
1388
|
+
}
|
1389
|
+
getNewSelectionFromExisting(previousSelection) {
|
1390
|
+
if (DateInput.isSelectionRange(previousSelection)) {
|
1391
|
+
// Base the year range off of the existing selection's end date, falling back to the start date
|
1392
|
+
const date = previousSelection.end || previousSelection.start;
|
1393
|
+
if (date) {
|
1394
|
+
return this.getSelectionFromDate(date);
|
1395
|
+
}
|
1396
|
+
}
|
1397
|
+
else if (DateInput.isSelectionSingleDate(previousSelection)) {
|
1398
|
+
// If the previous selection was a single date, make the range that year
|
1399
|
+
return this.getSelectionFromDate(previousSelection);
|
1400
|
+
}
|
1401
|
+
return null;
|
1402
|
+
}
|
1403
|
+
getSelectionForQuickSelectDate(date) {
|
1404
|
+
return this.getSelectionFromDate(date);
|
1405
|
+
}
|
1406
|
+
getNextSelection(selection) {
|
1407
|
+
// Move the selection to the next year
|
1408
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
1409
|
+
const date = moment(selection.start).add(1, 'year');
|
1410
|
+
return this.getSelectionFromDate(date.toDate());
|
1411
|
+
}
|
1412
|
+
// This shouldn't happen since the next stepper is disabled if the selection only has one date.
|
1413
|
+
// If it does, just return the selection as-is.
|
1414
|
+
return selection;
|
1415
|
+
}
|
1416
|
+
getPreviousSelection(selection) {
|
1417
|
+
// Move the selection to the previous year
|
1418
|
+
if (DateInput.isSelectionRange(selection) && selection.start) {
|
1419
|
+
const date = moment(selection.start).subtract(1, 'year');
|
1420
|
+
return this.getSelectionFromDate(date.toDate());
|
1421
|
+
}
|
1422
|
+
// This shouldn't happen since the previous stepper is disabled if the selection only has one date.
|
1423
|
+
// If it does, just return the selection as-is.
|
1424
|
+
return selection;
|
1425
|
+
}
|
1426
|
+
}
|
1427
|
+
|
1428
|
+
class UserPreferenceService {
|
1429
|
+
getPreferences() {
|
1430
|
+
return of({ preference: { dateFormat: 'MM/DD/YYYY', timeFormat: 'h:mm:ss a' } });
|
1431
|
+
}
|
1432
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserPreferenceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
1433
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserPreferenceService, providedIn: 'root' }); }
|
1434
|
+
}
|
1435
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserPreferenceService, decorators: [{
|
1436
|
+
type: Injectable,
|
1437
|
+
args: [{
|
1438
|
+
providedIn: 'root'
|
1439
|
+
}]
|
1440
|
+
}] });
|
1441
|
+
|
1442
|
+
/**
|
1443
|
+
* Format a date to the user's preference for display
|
1444
|
+
*/
|
1445
|
+
class DateDisplayPipe {
|
1446
|
+
constructor(userPreferenceService) {
|
1447
|
+
this.userPreferenceService = userPreferenceService;
|
1448
|
+
this.lastFormatString = 'MM/DD/YYYY';
|
1449
|
+
}
|
1450
|
+
/**
|
1451
|
+
* Format a date for display, accounting for user's display preferences.
|
1452
|
+
*
|
1453
|
+
* If {@see date} is null or undefined, or the end of time, returns empty string
|
1454
|
+
*/
|
1455
|
+
transform(date, showEndOfTime, showTime, showSeconds) {
|
1456
|
+
let display = '';
|
1457
|
+
let formatString = '';
|
1458
|
+
if (date && moment(date).isValid() && (showEndOfTime || !DateTimeHelper.isEndOfTime(date))) {
|
1459
|
+
// use user-preferred formats
|
1460
|
+
this.userPreferenceService.getPreferences().subscribe(result => {
|
1461
|
+
//if preferences exist then format date to users preference
|
1462
|
+
//otherwise use the last user preference
|
1463
|
+
if (result.preference) {
|
1464
|
+
formatString = result.preference.dateFormat;
|
1465
|
+
if (showTime) {
|
1466
|
+
let timeFormat = result.preference.timeFormat;
|
1467
|
+
if (!showSeconds) {
|
1468
|
+
timeFormat = timeFormat.replace(':ss', '');
|
1469
|
+
}
|
1470
|
+
formatString += ` ${timeFormat}`;
|
1471
|
+
}
|
1472
|
+
this.lastFormatString = formatString;
|
1473
|
+
}
|
1474
|
+
});
|
1475
|
+
display = moment(date).format(this.lastFormatString);
|
1476
|
+
}
|
1477
|
+
return display;
|
1478
|
+
}
|
1479
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateDisplayPipe, deps: [{ token: UserPreferenceService }], target: i0.ɵɵFactoryTarget.Pipe }); }
|
1480
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: DateDisplayPipe, name: "dateDisplay" }); }
|
1481
|
+
}
|
1482
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateDisplayPipe, decorators: [{
|
1483
|
+
type: Pipe,
|
1484
|
+
args: [{ name: 'dateDisplay' }]
|
1485
|
+
}], ctorParameters: () => [{ type: UserPreferenceService }] });
|
1486
|
+
|
1487
|
+
var DateInput;
|
1488
|
+
(function (DateInput) {
|
1489
|
+
function isSelectionSingleDate(selection) {
|
1490
|
+
return selection instanceof Date;
|
1491
|
+
}
|
1492
|
+
DateInput.isSelectionSingleDate = isSelectionSingleDate;
|
1493
|
+
function isSelectionRange(selection) {
|
1494
|
+
return !!selection && !isSelectionSingleDate(selection);
|
1495
|
+
}
|
1496
|
+
DateInput.isSelectionRange = isSelectionRange;
|
1497
|
+
class SelectionStrategies {
|
1498
|
+
constructor(dateDisplayPipe) {
|
1499
|
+
this.dateDisplayPipe = dateDisplayPipe;
|
1500
|
+
this._range = new RangeSelectionStrategy();
|
1501
|
+
this._day = new DaySelectionStrategy(this.dateDisplayPipe);
|
1502
|
+
this._last7Days = new Last7DaysSelectionStrategy(this._range);
|
1503
|
+
this._last28Days = new Last28DaysSelectionStrategy(this._range);
|
1504
|
+
this._month = new MonthSelectionStrategy();
|
1505
|
+
this._quarter = new QuarterSelectionStrategy();
|
1506
|
+
this._year = new YearSelectionStrategy();
|
1507
|
+
}
|
1508
|
+
get range() { return this._range; }
|
1509
|
+
get day() { return this._day; }
|
1510
|
+
get last7Days() { return this._last7Days; }
|
1511
|
+
get last28Days() { return this._last28Days; }
|
1512
|
+
get month() { return this._month; }
|
1513
|
+
get quarter() { return this._quarter; }
|
1514
|
+
get year() { return this._year; }
|
1515
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectionStrategies, deps: [{ token: DateDisplayPipe }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
1516
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectionStrategies }); }
|
1517
|
+
}
|
1518
|
+
DateInput.SelectionStrategies = SelectionStrategies;
|
1519
|
+
})(DateInput || (DateInput = {}));
|
1520
|
+
|
1521
|
+
class CalendarItemComponent {
|
1522
|
+
get disabled() {
|
1523
|
+
return this.hidden || undefined;
|
1524
|
+
}
|
1525
|
+
constructor() {
|
1526
|
+
this.view = { mode: 'day', date: new Date() };
|
1527
|
+
this.minDate = DateTimeHelper.minDatePickerDate;
|
1528
|
+
this.maxDate = DateTimeHelper.maxDatePickerDate;
|
1529
|
+
this.today = false;
|
1530
|
+
this.selected = false;
|
1531
|
+
this.outsideActiveMonth = false;
|
1532
|
+
this.hidden = false;
|
1533
|
+
}
|
1534
|
+
ngOnChanges() {
|
1535
|
+
if (this.view.mode !== 'day') {
|
1536
|
+
this.today = false;
|
1537
|
+
this.outsideActiveMonth = false;
|
1538
|
+
}
|
1539
|
+
else {
|
1540
|
+
this.today = moment(this.item?.date).isSame(moment(), 'day');
|
1541
|
+
this.outsideActiveMonth = !moment(this.item?.date).isSame(this.view.date, 'month');
|
1542
|
+
}
|
1543
|
+
if (this.item?.date) {
|
1544
|
+
this.hidden = this.isHidden(this.item.date, this.minDate, this.maxDate, this.view.mode);
|
1545
|
+
}
|
1546
|
+
else {
|
1547
|
+
this.hidden = true;
|
1548
|
+
}
|
1549
|
+
this.selected = this.isSelected(this.item?.date, this.selection, this.view.mode);
|
1550
|
+
}
|
1551
|
+
isSelected(date, selection, view) {
|
1552
|
+
if (!date || !selection) {
|
1553
|
+
return false;
|
1554
|
+
}
|
1555
|
+
if (DateInput.isSelectionSingleDate(selection)) {
|
1556
|
+
return moment(date).isSame(selection, view);
|
1557
|
+
}
|
1558
|
+
else {
|
1559
|
+
if (selection.start && !selection.end) {
|
1560
|
+
return moment(date).isSame(selection.start, view);
|
1561
|
+
}
|
1562
|
+
else if (!selection.start && selection.end) {
|
1563
|
+
return moment(date).isSame(selection.end, view);
|
1564
|
+
}
|
1565
|
+
else if (selection.start && selection.end) {
|
1566
|
+
return moment(date).isBetween(selection.start, selection.end, view, '[]');
|
1567
|
+
}
|
1568
|
+
}
|
1569
|
+
return false;
|
1570
|
+
}
|
1571
|
+
isHidden(date, minDate, maxDate, view) {
|
1572
|
+
return moment(date).isBefore(minDate, view) || moment(date).isAfter(maxDate, view);
|
1573
|
+
}
|
1574
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
1575
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CalendarItemComponent, selector: "button[ec-calendar-item]", inputs: { item: "item", selection: "selection", view: "view", minDate: "minDate", maxDate: "maxDate" }, host: { properties: { "class.is-today": "this.today", "class.is-selected": "this.selected", "class.is-outside-active-month": "this.outsideActiveMonth", "class.is-hidden": "this.hidden", "attr.disabled": "this.disabled" } }, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;line-height:1.125rem}:host .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}:host .ec-icon{flex:none}:host .ec-icon+.label{flex:none;margin-left:.25rem}:host.has-badge{padding-right:.0625rem}:host:focus{outline:none;position:relative;z-index:1}:host:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}:host:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}:host:hover:not(:disabled){background-color:var(--ec-background-color-hover)}:host:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}:host:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}:host.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-selected,:host.is-selected:disabled{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-today{text-decoration:underline}:host.is-outside-active-month{color:var(--ec-color-hint-dark)}:host.is-hidden{opacity:0!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
1576
|
+
}
|
1577
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarItemComponent, decorators: [{
|
1578
|
+
type: Component,
|
1579
|
+
args: [{ selector: 'button[ec-calendar-item]', template: '<ng-content></ng-content>', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;line-height:1.125rem}:host .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}:host .ec-icon{flex:none}:host .ec-icon+.label{flex:none;margin-left:.25rem}:host.has-badge{padding-right:.0625rem}:host:focus{outline:none;position:relative;z-index:1}:host:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}:host:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}:host:hover:not(:disabled){background-color:var(--ec-background-color-hover)}:host:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}:host:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}:host.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-selected,:host.is-selected:disabled{background-color:var(--ec-background-color-selected);font-weight:700}:host.is-today{text-decoration:underline}:host.is-outside-active-month{color:var(--ec-color-hint-dark)}:host.is-hidden{opacity:0!important}\n"] }]
|
1580
|
+
}], ctorParameters: () => [], propDecorators: { item: [{
|
1581
|
+
type: Input
|
1582
|
+
}], selection: [{
|
1583
|
+
type: Input
|
1584
|
+
}], view: [{
|
1585
|
+
type: Input
|
1586
|
+
}], minDate: [{
|
1587
|
+
type: Input
|
1588
|
+
}], maxDate: [{
|
1589
|
+
type: Input
|
1590
|
+
}], today: [{
|
1591
|
+
type: HostBinding,
|
1592
|
+
args: ['class.is-today']
|
1593
|
+
}], selected: [{
|
1594
|
+
type: HostBinding,
|
1595
|
+
args: ['class.is-selected']
|
1596
|
+
}], outsideActiveMonth: [{
|
1597
|
+
type: HostBinding,
|
1598
|
+
args: ['class.is-outside-active-month']
|
1599
|
+
}], hidden: [{
|
1600
|
+
type: HostBinding,
|
1601
|
+
args: ['class.is-hidden']
|
1602
|
+
}], disabled: [{
|
1603
|
+
type: HostBinding,
|
1604
|
+
args: ['attr.disabled']
|
1605
|
+
}] } });
|
1606
|
+
|
736
1607
|
class CalendarComponent {
|
737
1608
|
constructor() {
|
738
1609
|
this.id = 'calendar';
|
739
1610
|
this.selection = null;
|
740
|
-
this.
|
1611
|
+
this.selectionMode = 'day';
|
741
1612
|
this.minDate = DateTimeHelper.minDatePickerDate;
|
742
1613
|
this.maxDate = DateTimeHelper.maxDatePickerDate;
|
743
|
-
this.
|
744
|
-
|
745
|
-
|
1614
|
+
this.dateSelected = new EventEmitter();
|
1615
|
+
/** Determines the current view of the calendar. */
|
1616
|
+
this.view = { mode: 'day', date: new Date() };
|
1617
|
+
this.viewChange = new EventEmitter();
|
1618
|
+
/** Array of calendar item rows to display in the calendar. */
|
746
1619
|
this.calendarItems = [];
|
747
|
-
/**
|
748
|
-
this.
|
749
|
-
/** TrackBy function for the calendar items. This avoids re-drawing calendar items if a date is shared between view updates */
|
750
|
-
this.calendarItemTrackByDate = (index, item) => item.date.toISOString();
|
1620
|
+
/** Weekday labels to show at the top of the calendar in day view. */
|
1621
|
+
this.weekDays = moment.weekdaysShort().map(d => d.slice(0, 1));
|
751
1622
|
this.disablePreviousButton = false;
|
752
1623
|
this.disableNextButton = false;
|
753
|
-
//
|
754
|
-
//
|
755
|
-
this.
|
756
|
-
|
757
|
-
this.weekDays = moment.weekdaysShort().map(d => d.slice(0, 1));
|
1624
|
+
// Trackby functions for ngFor loops. These reduce the number of DOM elements that need to be updated when the calendar is re-drawn.
|
1625
|
+
// Without these there are some change-detection issues on the first-time rendering of the calendar.
|
1626
|
+
this.trackByDateRow = (index, row) => `${row[0].date.toISOString()}-${row[row.length - 1].date.toISOString()}`;
|
1627
|
+
this.trackByDate = (index, item) => item.date.toISOString();
|
758
1628
|
}
|
759
1629
|
ngOnChanges(changes) {
|
760
|
-
if (changes.
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
this.drawCalendar('day', this.selection);
|
766
|
-
}
|
767
|
-
else {
|
768
|
-
// TODO ECAP-26841: determine the active date for a range selection and draw the calendar
|
769
|
-
}
|
1630
|
+
if (changes.view) {
|
1631
|
+
this.drawCalendar(this.view);
|
1632
|
+
}
|
1633
|
+
if (changes.minDate || changes.maxDate) {
|
1634
|
+
this.updateNextPreviousStates();
|
770
1635
|
}
|
771
1636
|
}
|
772
1637
|
ngOnInit() {
|
773
1638
|
if (!this.calendarItems.length) {
|
774
|
-
this.drawCalendar(
|
775
|
-
}
|
776
|
-
}
|
777
|
-
onItemSelected(item) {
|
778
|
-
if (this.view === 'day') {
|
779
|
-
this.selection = item.date;
|
780
|
-
this.selectionChange.emit(this.selection);
|
781
|
-
}
|
782
|
-
if (this.view === 'month') {
|
783
|
-
this.drawCalendar('day', item.date);
|
784
|
-
}
|
785
|
-
if (this.view === 'year') {
|
786
|
-
this.drawCalendar('month', item.date);
|
1639
|
+
this.drawCalendar(this.view);
|
787
1640
|
}
|
788
1641
|
}
|
789
1642
|
onNextClick() {
|
790
1643
|
// If we're in day view, we're incrementing by month
|
791
|
-
// In
|
792
|
-
|
793
|
-
const unit = this.view === 'day' ? 'month' : 'year';
|
1644
|
+
// In month, quarter, and year views we're incrementing by year\
|
1645
|
+
const unit = this.view.mode === 'day' ? 'month' : 'year';
|
794
1646
|
// In year view, we're moving by 16 years at a time. Otherwise we're just moving by 1 month/year.
|
795
|
-
const count = this.view === 'year' ? 16 : 1;
|
796
|
-
const goToDate = moment(this.
|
797
|
-
this.drawCalendar(this.view, goToDate);
|
1647
|
+
const count = this.view.mode === 'year' ? 16 : 1;
|
1648
|
+
const goToDate = moment(this.view.date).add(count, unit).toDate();
|
1649
|
+
this.drawCalendar({ mode: this.view.mode, date: goToDate });
|
798
1650
|
}
|
799
1651
|
onPreviousClick() {
|
800
1652
|
// If we're in day view, we're incrementing by month
|
801
|
-
// In
|
802
|
-
const unit = this.view === 'day' ? 'month' : 'year';
|
1653
|
+
// In month, quarter, and year views we're incrementing by year
|
1654
|
+
const unit = this.view.mode === 'day' ? 'month' : 'year';
|
803
1655
|
// In year view, we're moving by 16 years at a time. Otherwise we're just moving by 1 month/year.
|
804
|
-
const count = this.view === 'year' ? 16 : 1;
|
805
|
-
const goToDate = moment(this.
|
806
|
-
this.drawCalendar(this.view, goToDate);
|
1656
|
+
const count = this.view.mode === 'year' ? 16 : 1;
|
1657
|
+
const goToDate = moment(this.view.date).subtract(count, unit).toDate();
|
1658
|
+
this.drawCalendar({ mode: this.view.mode, date: goToDate });
|
807
1659
|
}
|
808
1660
|
/** Switches the calendar to month view. */
|
809
1661
|
onMonthClick() {
|
810
|
-
this.drawCalendar('month');
|
1662
|
+
this.drawCalendar({ mode: 'month', date: this.view.date });
|
811
1663
|
}
|
812
1664
|
/** Switches the calendar to year view. */
|
813
1665
|
onYearClick() {
|
814
|
-
this.drawCalendar('year');
|
815
|
-
}
|
816
|
-
onFirstItemKeydown(event) {
|
817
|
-
// If the user is tabbing backwards from the first item, emit the focusOutStart event.
|
818
|
-
if (event.key === 'Tab' && event.shiftKey) {
|
819
|
-
this.focusOutStart.emit(event);
|
820
|
-
}
|
1666
|
+
this.drawCalendar({ mode: 'year', date: this.view.date });
|
821
1667
|
}
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
1668
|
+
onItemSelected(item) {
|
1669
|
+
switch (this.view.mode) {
|
1670
|
+
case 'day':
|
1671
|
+
this.onDaySelected(item);
|
1672
|
+
break;
|
1673
|
+
case 'month':
|
1674
|
+
this.onMonthSelected(item);
|
1675
|
+
break;
|
1676
|
+
case 'quarter':
|
1677
|
+
this.onQuarterSelected(item);
|
1678
|
+
break;
|
1679
|
+
case 'year':
|
1680
|
+
this.onYearSelected(item);
|
1681
|
+
break;
|
826
1682
|
}
|
827
1683
|
}
|
828
|
-
|
829
|
-
// If
|
830
|
-
if (
|
831
|
-
this.
|
1684
|
+
onYearSelected(item) {
|
1685
|
+
// If in year selection mode, emit the calendar item so the date picker can update the selection.
|
1686
|
+
if (this.selectionMode === 'year') {
|
1687
|
+
this.dateSelected.emit(item.date);
|
1688
|
+
// If we're in quarter selection mode, draw the quarter view.
|
832
1689
|
}
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
this.calendarItems = this.getCalendarItems(view, this.activeDate);
|
837
|
-
const startYear = this.calendarItems[0].date < this.minDate ? this.minDate : this.calendarItems[0].date;
|
838
|
-
const endYear = this.calendarItems[this.calendarItems.length - 1].date > this.maxDate ? this.maxDate : this.calendarItems[this.calendarItems.length - 1].date;
|
839
|
-
this.yearRange = `${moment(startYear).format('YYYY')}–${moment(endYear).format('YYYY')}`;
|
840
|
-
// If the active date is less than the min date or the min date is in view, disable the previous button.
|
841
|
-
if (this.activeDate < this.minDate || this.isDateInView(this.minDate)) {
|
842
|
-
this.disablePreviousButton = true;
|
1690
|
+
else if (this.selectionMode === 'quarter') {
|
1691
|
+
this.drawCalendar({ mode: 'quarter', date: item.date });
|
1692
|
+
// All other selection modes should zoom in to the month view when a year is selected.
|
843
1693
|
}
|
844
1694
|
else {
|
845
|
-
this.
|
1695
|
+
this.drawCalendar({ mode: 'month', date: item.date });
|
846
1696
|
}
|
847
|
-
|
848
|
-
|
849
|
-
|
1697
|
+
}
|
1698
|
+
onQuarterSelected(item) {
|
1699
|
+
// Quarter view is only accessible when in quarter selection mode,
|
1700
|
+
// so there's no other views to draw from here. Just emit the selected item.
|
1701
|
+
this.dateSelected.emit(item.date);
|
1702
|
+
}
|
1703
|
+
onMonthSelected(item) {
|
1704
|
+
// When in month selection mode, emit the selected month item and don't change the view.
|
1705
|
+
if (this.selectionMode === 'month') {
|
1706
|
+
this.dateSelected.emit(item.date);
|
1707
|
+
// Month view is only accessible from day, last7days, last28days, month, and range selection modes.
|
1708
|
+
// If we're not in month selection mode, we need to zoom in to the day view.
|
850
1709
|
}
|
851
1710
|
else {
|
852
|
-
this.
|
1711
|
+
this.drawCalendar({ mode: 'day', date: item.date });
|
1712
|
+
}
|
1713
|
+
}
|
1714
|
+
onDaySelected(item) {
|
1715
|
+
// No further views other than day mode. Just emit the selected item.
|
1716
|
+
this.dateSelected.emit(item.date);
|
1717
|
+
}
|
1718
|
+
drawCalendar(view) {
|
1719
|
+
// If the view has changed, emit the new view.
|
1720
|
+
if (view.date !== this.view.date || view.mode !== this.view.mode) {
|
1721
|
+
this.view = view;
|
1722
|
+
this.viewChange.emit(view);
|
853
1723
|
}
|
1724
|
+
this.month = moment(this.view.date).format('MMM');
|
1725
|
+
this.year = moment(this.view.date).format('YYYY');
|
1726
|
+
this.calendarItems = this.getCalendarItems(this.view);
|
1727
|
+
const startYear = this.calendarItems[0][0].date < this.minDate ? this.minDate : this.calendarItems[0][0].date;
|
1728
|
+
const lastItem = this.getLastItem();
|
1729
|
+
const endYear = lastItem.date > this.maxDate ? this.maxDate : lastItem.date;
|
1730
|
+
this.yearRange = `${moment(startYear).format('YYYY')}–${moment(endYear).format('YYYY')}`;
|
1731
|
+
this.updateNextPreviousStates();
|
854
1732
|
}
|
855
|
-
getCalendarItems(view
|
856
|
-
switch (view) {
|
857
|
-
case 'day': return this.getDayViewItems(
|
858
|
-
case 'month': return this.getMonthViewItems(
|
859
|
-
case '
|
1733
|
+
getCalendarItems(view) {
|
1734
|
+
switch (view.mode) {
|
1735
|
+
case 'day': return this.getDayViewItems(view.date);
|
1736
|
+
case 'month': return this.getMonthViewItems(view.date);
|
1737
|
+
case 'quarter': return this.getQuarterViewItems(view.date);
|
1738
|
+
case 'year': return this.getYearViewItems(view.date);
|
860
1739
|
}
|
861
1740
|
}
|
862
1741
|
getDayViewItems(activeDate) {
|
863
1742
|
// 6 rows of 7 days = 42 days
|
864
|
-
return range(0,
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
1743
|
+
return range(0, 6).map(r => {
|
1744
|
+
return range(0, 7).map(d => {
|
1745
|
+
// Use the start of the week of the first day of the month.
|
1746
|
+
// This pads out the first week with any days from the previous month.
|
1747
|
+
const date = moment(activeDate).startOf('month').startOf('week').add(r * 7 + d, 'day');
|
1748
|
+
return {
|
1749
|
+
date: date.toDate(),
|
1750
|
+
label: date.format('D')
|
1751
|
+
};
|
1752
|
+
});
|
872
1753
|
});
|
873
1754
|
}
|
874
1755
|
getMonthViewItems(activeDate) {
|
875
|
-
|
876
|
-
|
877
|
-
return {
|
878
|
-
date
|
879
|
-
|
880
|
-
|
1756
|
+
// 4 rows of 3 months = 12 months
|
1757
|
+
return range(0, 4).map(r => {
|
1758
|
+
return range(0, 3).map(m => {
|
1759
|
+
const date = moment(activeDate).startOf('year').add(r * 3 + m, 'month');
|
1760
|
+
return {
|
1761
|
+
date: date.toDate(),
|
1762
|
+
label: date.format('MMM')
|
1763
|
+
};
|
1764
|
+
});
|
1765
|
+
});
|
1766
|
+
}
|
1767
|
+
getQuarterViewItems(activeDate) {
|
1768
|
+
// 2 rows of 2 quarters = 4 quarters
|
1769
|
+
return range(0, 2).map(r => {
|
1770
|
+
return range(0, 2).map(q => {
|
1771
|
+
const date = moment(activeDate).startOf('year').add(r * 2 + q, 'quarter');
|
1772
|
+
const endDate = moment(date).endOf('quarter');
|
1773
|
+
return {
|
1774
|
+
date: date.toDate(),
|
1775
|
+
label: `${date.format('MMM')}–${endDate.format('MMM')}`
|
1776
|
+
};
|
1777
|
+
});
|
881
1778
|
});
|
882
1779
|
}
|
883
1780
|
getYearViewItems(activeDate) {
|
884
|
-
//
|
885
|
-
return range(0,
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
1781
|
+
// 4 rows of 4 years = 16 years
|
1782
|
+
return range(0, 4).map(r => {
|
1783
|
+
return range(0, 4).map(y => {
|
1784
|
+
// Subtracting 8 years to put the current active year at the beginning of the 3rd row.
|
1785
|
+
const date = moment(activeDate).startOf('year').subtract(8, 'years').add(r * 4 + y, 'year');
|
1786
|
+
return {
|
1787
|
+
date: date.toDate(),
|
1788
|
+
label: date.format('YYYY')
|
1789
|
+
};
|
1790
|
+
});
|
892
1791
|
});
|
893
1792
|
}
|
894
|
-
|
895
|
-
|
896
|
-
if
|
897
|
-
|
1793
|
+
updateNextPreviousStates() {
|
1794
|
+
// We change the granularity of the min and max date checks based on the current view mode.
|
1795
|
+
// We don't want to disable the next/previous buttons if the min or max date is within the
|
1796
|
+
// next or previous view
|
1797
|
+
const unit = this.view.mode === 'day' ? 'month' : 'year';
|
1798
|
+
// When in year view, we need to subtract 9 years to determine if we're past the min date.
|
1799
|
+
// The year view is 16 years long, and the current date is the 9th year in the view.
|
1800
|
+
const subCount = this.view.mode === 'year' ? 9 : 1;
|
1801
|
+
if (moment(this.view.date).subtract(subCount, unit).isBefore(this.minDate, unit)) {
|
1802
|
+
this.disablePreviousButton = true;
|
1803
|
+
}
|
1804
|
+
else {
|
1805
|
+
this.disablePreviousButton = false;
|
1806
|
+
}
|
1807
|
+
// When in year view, we need to add 8 years to determine if we're past the max date.
|
1808
|
+
// The year view is 16 years long, and the current date is the 9th year in the view.
|
1809
|
+
const addCount = this.view.mode === 'year' ? 8 : 1;
|
1810
|
+
if (moment(this.view.date).add(addCount, unit).isAfter(this.maxDate, unit)) {
|
1811
|
+
this.disableNextButton = true;
|
898
1812
|
}
|
899
|
-
|
900
|
-
|
901
|
-
|
1813
|
+
else {
|
1814
|
+
this.disableNextButton = false;
|
1815
|
+
}
|
1816
|
+
}
|
1817
|
+
getLastItem() {
|
1818
|
+
const lastRow = this.calendarItems[this.calendarItems.length - 1];
|
1819
|
+
return lastRow[lastRow.length - 1];
|
902
1820
|
}
|
903
1821
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
904
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CalendarComponent, selector: "ec-calendar", inputs: { id: "id", selection: "selection", minDate: "minDate", maxDate: "maxDate" }, outputs: {
|
1822
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CalendarComponent, selector: "ec-calendar", inputs: { id: "id", selection: "selection", selectionMode: "selectionMode", minDate: "minDate", maxDate: "maxDate", view: "view" }, outputs: { dateSelected: "dateSelected", viewChange: "viewChange" }, host: { properties: { "attr.id": "this.id" } }, usesOnChanges: true, ngImport: i0, template: "<header class=\"d-flex align-items-center mt-1 mb-2 px-1\">\r\n <button id=\"{{id}}_prev_button\"\r\n class=\"mr-auto\"\r\n (click)=\"onPreviousClick()\"\r\n [disabled]=\"disablePreviousButton\">\r\n <i class=\"ec-icon icon-angle-down rotate-90\"></i>\r\n </button>\r\n\r\n <button *ngIf=\"view.mode === 'day'\"\r\n id=\"{{id}}_month_button\"\r\n class=\"text-body-1 font-weight-bold\"\r\n (click)=\"onMonthClick()\">\r\n {{month}}\r\n </button>\r\n\r\n <button *ngIf=\"view.mode !== 'year'\"\r\n id=\"{{id}}_year_button\"\r\n class=\"text-body-1 font-weight-bold\"\r\n (click)=\"onYearClick()\">\r\n {{year}}\r\n </button>\r\n\r\n <div id=\"{{id}}_year_range\"\r\n *ngIf=\"view.mode === 'year'\"\r\n class=\"text-body-1 font-weight-bold\"\r\n [innerHTML]=\"yearRange\">\r\n </div>\r\n\r\n <button id=\"{{id}}_next_button\"\r\n class=\"ml-auto\"\r\n (click)=\"onNextClick()\"\r\n [disabled]=\"disableNextButton\">\r\n <i class=\"ec-icon icon-angle-down rotate-270\"></i>\r\n </button>\r\n</header>\r\n\r\n<div *ngIf=\"view.mode === 'day'\"\r\n class=\"mb-1 px-2 d-flex\">\r\n <h3 *ngFor=\"let day of weekDays\"\r\n class=\"text-heading-3 d-flex justify-content-center align-items-center\"\r\n style=\"width: 2rem; height: 1.75rem;\">{{day}}</h3>\r\n</div>\r\n\r\n<div *ngFor=\"let row of calendarItems; last as isLast; trackBy: trackByDateRow\"\r\n class=\"px-2 d-flex {{view.mode}}-view\"\r\n [class.mb-1]=\"!isLast\"\r\n [class.mb-2]=\"isLast\">\r\n <button *ngFor=\"let item of row; trackBy: trackByDate\"\r\n id=\"{{id}}_item_{{item.date | date:'MM_dd_yyyy'}}\"\r\n ec-calendar-item\r\n [item]=\"item\"\r\n [selection]=\"selection\"\r\n [view]=\"view\"\r\n (click)=\"onItemSelected(item)\"\r\n [innerHTML]=\"item.label\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\">\r\n </button>\r\n</div>\r\n", styles: [":host{display:inline-block}button{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent}button .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}button .ec-icon{flex:none}button .ec-icon+.label{flex:none;margin-left:.25rem}button.has-badge{padding-right:.0625rem}button:focus{outline:none;position:relative;z-index:1}button:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}button:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}button:hover:not(:disabled){background-color:var(--ec-background-color-hover)}button:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}button:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}button.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}.day-view button{width:2rem;height:1.75rem}.month-view button{width:4.67rem;height:3.25rem}.quarter-view button{width:7rem;height:6.75rem}.year-view button{width:3.5rem;height:3.25rem}.is-selected:has(+.is-selected:not(:disabled)){border-top-right-radius:0;border-bottom-right-radius:0}.is-selected:not(:disabled)+.is-selected{border-top-left-radius:0;border-bottom-left-radius:0}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CalendarItemComponent, selector: "button[ec-calendar-item]", inputs: ["item", "selection", "view", "minDate", "maxDate"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
905
1823
|
}
|
906
1824
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, decorators: [{
|
907
1825
|
type: Component,
|
908
|
-
args: [{ selector: 'ec-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"d-flex align-items-center mb-2\">\r\n <button id=\"{{id}}_prev_button\"\r\n class=\"mr-auto\"\r\n (click)=\"onPreviousClick()\"\r\n
|
909
|
-
}],
|
1826
|
+
args: [{ selector: 'ec-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"d-flex align-items-center mt-1 mb-2 px-1\">\r\n <button id=\"{{id}}_prev_button\"\r\n class=\"mr-auto\"\r\n (click)=\"onPreviousClick()\"\r\n [disabled]=\"disablePreviousButton\">\r\n <i class=\"ec-icon icon-angle-down rotate-90\"></i>\r\n </button>\r\n\r\n <button *ngIf=\"view.mode === 'day'\"\r\n id=\"{{id}}_month_button\"\r\n class=\"text-body-1 font-weight-bold\"\r\n (click)=\"onMonthClick()\">\r\n {{month}}\r\n </button>\r\n\r\n <button *ngIf=\"view.mode !== 'year'\"\r\n id=\"{{id}}_year_button\"\r\n class=\"text-body-1 font-weight-bold\"\r\n (click)=\"onYearClick()\">\r\n {{year}}\r\n </button>\r\n\r\n <div id=\"{{id}}_year_range\"\r\n *ngIf=\"view.mode === 'year'\"\r\n class=\"text-body-1 font-weight-bold\"\r\n [innerHTML]=\"yearRange\">\r\n </div>\r\n\r\n <button id=\"{{id}}_next_button\"\r\n class=\"ml-auto\"\r\n (click)=\"onNextClick()\"\r\n [disabled]=\"disableNextButton\">\r\n <i class=\"ec-icon icon-angle-down rotate-270\"></i>\r\n </button>\r\n</header>\r\n\r\n<div *ngIf=\"view.mode === 'day'\"\r\n class=\"mb-1 px-2 d-flex\">\r\n <h3 *ngFor=\"let day of weekDays\"\r\n class=\"text-heading-3 d-flex justify-content-center align-items-center\"\r\n style=\"width: 2rem; height: 1.75rem;\">{{day}}</h3>\r\n</div>\r\n\r\n<div *ngFor=\"let row of calendarItems; last as isLast; trackBy: trackByDateRow\"\r\n class=\"px-2 d-flex {{view.mode}}-view\"\r\n [class.mb-1]=\"!isLast\"\r\n [class.mb-2]=\"isLast\">\r\n <button *ngFor=\"let item of row; trackBy: trackByDate\"\r\n id=\"{{id}}_item_{{item.date | date:'MM_dd_yyyy'}}\"\r\n ec-calendar-item\r\n [item]=\"item\"\r\n [selection]=\"selection\"\r\n [view]=\"view\"\r\n (click)=\"onItemSelected(item)\"\r\n [innerHTML]=\"item.label\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\">\r\n </button>\r\n</div>\r\n", styles: [":host{display:inline-block}button{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent}button .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}button .ec-icon{flex:none}button .ec-icon+.label{flex:none;margin-left:.25rem}button.has-badge{padding-right:.0625rem}button:focus{outline:none;position:relative;z-index:1}button:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}button:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}button:hover:not(:disabled){background-color:var(--ec-background-color-hover)}button:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}button:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}button.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}.day-view button{width:2rem;height:1.75rem}.month-view button{width:4.67rem;height:3.25rem}.quarter-view button{width:7rem;height:6.75rem}.year-view button{width:3.5rem;height:3.25rem}.is-selected:has(+.is-selected:not(:disabled)){border-top-right-radius:0;border-bottom-right-radius:0}.is-selected:not(:disabled)+.is-selected{border-top-left-radius:0;border-bottom-left-radius:0}\n"] }]
|
1827
|
+
}], propDecorators: { id: [{
|
910
1828
|
type: HostBinding,
|
911
1829
|
args: ['attr.id']
|
912
1830
|
}, {
|
913
1831
|
type: Input
|
914
1832
|
}], selection: [{
|
915
1833
|
type: Input
|
916
|
-
}],
|
917
|
-
type:
|
1834
|
+
}], selectionMode: [{
|
1835
|
+
type: Input
|
918
1836
|
}], minDate: [{
|
919
1837
|
type: Input
|
920
1838
|
}], maxDate: [{
|
921
1839
|
type: Input
|
922
|
-
}],
|
1840
|
+
}], dateSelected: [{
|
923
1841
|
type: Output
|
924
|
-
}],
|
1842
|
+
}], view: [{
|
1843
|
+
type: Input
|
1844
|
+
}], viewChange: [{
|
925
1845
|
type: Output
|
926
1846
|
}] } });
|
927
1847
|
|
928
|
-
class UserPreferenceService {
|
929
|
-
getPreferences() {
|
930
|
-
return of({ preference: { dateFormat: 'MM/DD/YYYY', timeFormat: 'h:mm:ss a' } });
|
931
|
-
}
|
932
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserPreferenceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
933
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserPreferenceService, providedIn: 'root' }); }
|
934
|
-
}
|
935
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserPreferenceService, decorators: [{
|
936
|
-
type: Injectable,
|
937
|
-
args: [{
|
938
|
-
providedIn: 'root'
|
939
|
-
}]
|
940
|
-
}] });
|
941
|
-
|
942
|
-
/**
|
943
|
-
* Format a date to the user's preference for display
|
944
|
-
*/
|
945
|
-
class DateDisplayPipe {
|
946
|
-
constructor(userPreferenceService) {
|
947
|
-
this.userPreferenceService = userPreferenceService;
|
948
|
-
this.lastFormatString = 'MM/DD/YYYY';
|
949
|
-
}
|
950
|
-
/**
|
951
|
-
* Format a date for display, accounting for user's display preferences.
|
952
|
-
*
|
953
|
-
* If {@see date} is null or undefined, or the end of time, returns empty string
|
954
|
-
*/
|
955
|
-
transform(date, showEndOfTime, showTime, showSeconds) {
|
956
|
-
let display = '';
|
957
|
-
let formatString = '';
|
958
|
-
if (date && moment(date).isValid() && (showEndOfTime || !DateTimeHelper.isEndOfTime(date))) {
|
959
|
-
// use user-preferred formats
|
960
|
-
this.userPreferenceService.getPreferences().subscribe(result => {
|
961
|
-
//if preferences exist then format date to users preference
|
962
|
-
//otherwise use the last user preference
|
963
|
-
if (result.preference) {
|
964
|
-
formatString = result.preference.dateFormat;
|
965
|
-
if (showTime) {
|
966
|
-
let timeFormat = result.preference.timeFormat;
|
967
|
-
if (!showSeconds) {
|
968
|
-
timeFormat = timeFormat.replace(':ss', '');
|
969
|
-
}
|
970
|
-
formatString += ` ${timeFormat}`;
|
971
|
-
}
|
972
|
-
this.lastFormatString = formatString;
|
973
|
-
}
|
974
|
-
});
|
975
|
-
display = moment(date).format(this.lastFormatString);
|
976
|
-
}
|
977
|
-
return display;
|
978
|
-
}
|
979
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateDisplayPipe, deps: [{ token: UserPreferenceService }], target: i0.ɵɵFactoryTarget.Pipe }); }
|
980
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: DateDisplayPipe, name: "dateDisplay" }); }
|
981
|
-
}
|
982
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateDisplayPipe, decorators: [{
|
983
|
-
type: Pipe,
|
984
|
-
args: [{ name: 'dateDisplay' }]
|
985
|
-
}], ctorParameters: () => [{ type: UserPreferenceService }] });
|
986
|
-
|
987
1848
|
/**
|
988
1849
|
* "Weak Type" describing interpolation parameters for NumericBox
|
989
1850
|
*/
|
@@ -3906,6 +4767,9 @@ class FormControlComponent {
|
|
3906
4767
|
;
|
3907
4768
|
get disabled() { return this._formModel?.disabled == true; }
|
3908
4769
|
;
|
4770
|
+
get _formModel() {
|
4771
|
+
return this.formModelInput || this.formControlDirective;
|
4772
|
+
}
|
3909
4773
|
constructor(el) {
|
3910
4774
|
this.el = el;
|
3911
4775
|
this.id = '';
|
@@ -3915,15 +4779,8 @@ class FormControlComponent {
|
|
3915
4779
|
this.required = false;
|
3916
4780
|
this.readonly = false;
|
3917
4781
|
this.actionClicked = new EventEmitter();
|
3918
|
-
this.actionKeydown = new EventEmitter();
|
3919
|
-
}
|
3920
|
-
ngOnChanges(changes) {
|
3921
|
-
if (changes.formModelInput) {
|
3922
|
-
this._formModel = this.formModelInput || this.formControlDirective;
|
3923
|
-
}
|
3924
4782
|
}
|
3925
4783
|
ngAfterViewInit() {
|
3926
|
-
this._formModel = this.formModelInput || this.formControlDirective;
|
3927
4784
|
if (!this._formModel) {
|
3928
4785
|
console.error('Missing [formModel] input or [formControl] directive on ec-form-control content.');
|
3929
4786
|
}
|
@@ -3945,11 +4802,11 @@ class FormControlComponent {
|
|
3945
4802
|
this._formModel?.reset();
|
3946
4803
|
}
|
3947
4804
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormControlComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
3948
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FormControlComponent, selector: "ec-form-control", inputs: { id: "id", icon: "icon", actionIcon: "actionIcon", showClear: "showClear", formModelInput: ["formModel", "formModelInput"], autofocus: "autofocus", pending: "pending", required: "required", readonly: "readonly" }, outputs: { actionClicked: "actionClicked"
|
4805
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FormControlComponent, selector: "ec-form-control", inputs: { id: "id", icon: "icon", actionIcon: "actionIcon", showClear: "showClear", formModelInput: ["formModel", "formModelInput"], autofocus: "autofocus", pending: "pending", required: "required", readonly: "readonly" }, outputs: { actionClicked: "actionClicked" }, host: { listeners: { "click": "onClick()" }, properties: { "class.is-pending": "this.pending", "class.is-required": "this.required", "class.is-readonly": "this.readonly", "class.is-empty": "this.empty", "class.is-invalid": "this.invalid", "class.is-disabled": "this.disabled" } }, queries: [{ propertyName: "formControlDirective", first: true, predicate: FormControlDirective, descendants: true }], ngImport: i0, template: "<ng-content></ng-content>\r\n<i id=\"{{id + '_icon'}}\" class=\"ec-form-control-icon ec-icon {{icon}}\"></i>\r\n<i id=\"{{id + '_loading'}}\" class=\"ec-form-control-icon ec-icon icon-loading\"></i>\r\n<i id=\"{{id + '_required'}}\" class=\"ec-form-control-icon ec-icon icon-required\"></i>\r\n<i id=\"{{id + '_invalid'}}\" class=\"ec-form-control-icon ec-icon icon-invalid\"></i>\r\n<button *ngIf=\"showClear\"\r\n id=\"{{id + '_clear'}}\"\r\n [attr.disabled]=\"disabled || undefined\"\r\n class=\"ec-form-control-clear\"\r\n (click)=\"clear()\">\r\n <i class=\"ec-icon icon-cancel\"></i>\r\n</button>\r\n<button *ngIf=\"actionIcon\"\r\n id=\"{{id + '_action'}}\"\r\n [attr.disabled]=\"disabled || undefined\"\r\n class=\"ec-form-control-action\"\r\n (click)=\"actionClicked.emit($event)\">\r\n <i class=\"ec-icon {{actionIcon}}\"></i>\r\n</button>\r\n<div class=\"ec-focus-ring\"></div>\r\n", styles: ["ec-form-control{background-color:var(--ec-form-control-background-color);background-clip:padding-box;border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);padding:0 .5rem;position:relative;color:var(--ec-form-control-color);display:flex;font-size:var(--ec-form-control-font-size);min-height:2rem;width:100%}ec-form-control>input,ec-form-control>select,ec-form-control>textarea,ec-form-control>div[contenteditable=true]{color:inherit;flex:1 1;min-width:0;border:0;background-color:transparent;order:2}ec-form-control>input::selection,ec-form-control>select::selection,ec-form-control>textarea::selection,ec-form-control>div[contenteditable=true]::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}ec-form-control>input::-webkit-input-placeholder,ec-form-control>select::-webkit-input-placeholder,ec-form-control>textarea::-webkit-input-placeholder,ec-form-control>div[contenteditable=true]::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}ec-form-control>input::-moz-placeholder,ec-form-control>select::-moz-placeholder,ec-form-control>textarea::-moz-placeholder,ec-form-control>div[contenteditable=true]::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}ec-form-control>input:-ms-input-placeholder,ec-form-control>select:-ms-input-placeholder,ec-form-control>textarea:-ms-input-placeholder,ec-form-control>div[contenteditable=true]:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}ec-form-control>input:-moz-placeholder,ec-form-control>select:-moz-placeholder,ec-form-control>textarea:-moz-placeholder,ec-form-control>div[contenteditable=true]:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}ec-form-control>input:focus,ec-form-control>select:focus,ec-form-control>textarea:focus,ec-form-control>div[contenteditable=true]:focus{outline:none}ec-form-control>input:focus~.ec-focus-ring,ec-form-control>select:focus~.ec-focus-ring,ec-form-control>textarea:focus~.ec-focus-ring,ec-form-control>div[contenteditable=true]:focus~.ec-focus-ring{display:block}ec-form-control>input,ec-form-control>textarea,ec-form-control>select,ec-form-control>div[contenteditable=true],ec-form-control .ec-form-control-prefix,ec-form-control .ec-form-control-suffix{padding:calc((1.875rem - var(--ec-font-size-body) * 1.25) / 2) 0;line-height:1.25;font-size:inherit}ec-form-control>textarea{resize:none;padding:.3125rem 0}ec-form-control .ec-form-control-icon{margin-top:.4375rem;margin-right:.25rem;order:1}ec-form-control .ec-form-control-icon:not([class*=icon-]){display:none}ec-form-control .icon-required,ec-form-control .icon-invalid{color:var(--ec-form-control-border-color-invalid)}ec-form-control .ec-form-control-clear,ec-form-control .ec-form-control-action{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border-radius:var(--ec-border-radius);display:flex;cursor:pointer;flex:none;height:1.875rem;width:2rem;order:3;background-color:transparent;border:0;border-radius:0;display:inline-flex;align-items:center;justify-content:center;outline:none}ec-form-control .ec-form-control-clear .label,ec-form-control .ec-form-control-action .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}ec-form-control .ec-form-control-clear .ec-icon,ec-form-control .ec-form-control-action .ec-icon{flex:none}ec-form-control .ec-form-control-clear .ec-icon+.label,ec-form-control .ec-form-control-action .ec-icon+.label{flex:none;margin-left:.25rem}ec-form-control .ec-form-control-clear.has-badge,ec-form-control .ec-form-control-action.has-badge{padding-right:.0625rem}ec-form-control .ec-form-control-clear:focus,ec-form-control .ec-form-control-action:focus{outline:none;position:relative;z-index:1}ec-form-control .ec-form-control-clear:disabled,ec-form-control .ec-form-control-action:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}ec-form-control .ec-form-control-clear:disabled,ec-form-control .ec-form-control-action:disabled{border:0;background-color:transparent;border-color:transparent}ec-form-control .ec-form-control-clear:last-of-type,ec-form-control .ec-form-control-action:last-of-type{margin-right:-.5rem}ec-form-control .ec-form-control-clear:hover:not(:disabled),ec-form-control .ec-form-control-action:hover:not(:disabled){cursor:pointer;background-color:var(--ec-background-color-hover)}ec-form-control .ec-form-control-clear:active:not(:disabled),ec-form-control .ec-form-control-action:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}ec-form-control .ec-form-control-clear:focus:not(:disabled),ec-form-control .ec-form-control-action:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}ec-form-control button:last-of-type{border-top-right-radius:calc(var(--ec-form-control-border-radius) - .0625rem);border-bottom-right-radius:calc(var(--ec-form-control-border-radius) - .0625rem)}ec-form-control .ec-form-control-clear{width:1.5rem}ec-form-control .ec-form-control-prefix,ec-form-control .ec-form-control-suffix{color:var(--ec-color-secondary-dark);flex:none;cursor:default}ec-form-control .ec-form-control-prefix{margin-right:.125rem;order:2}ec-form-control .ec-form-control-suffix{margin-left:.125rem;order:3}ec-form-control .ec-focus-ring{position:absolute;inset:-1px;border:.125rem solid var(--ec-color-interactive);pointer-events:none;display:none;border-radius:var(--ec-form-control-border-radius);z-index:1}ec-form-control.is-pending .icon-invalid,ec-form-control.is-pending .icon-required{display:none}ec-form-control.is-invalid{border-color:var(--ec-form-control-border-color-invalid);background-color:var(--ec-form-control-background-color-invalid)}ec-form-control.is-invalid .icon-required{display:none}ec-form-control.is-empty .ec-form-control-clear{display:none}ec-form-control.is-required.is-empty .ec-form-control-icon:first-of-type{display:none}ec-form-control:not(.is-pending) .icon-loading{display:none}ec-form-control:not(.is-required) .icon-required,ec-form-control:not(.is-empty) .icon-required{display:none}ec-form-control:not(.is-invalid) .icon-invalid{display:none}ec-form-control.is-readonly,ec-form-control.is-disabled{background-color:var(--ec-form-control-background-color-disabled)}ec-form-control.is-readonly .icon-loading,ec-form-control.is-readonly .icon-invalid,ec-form-control.is-readonly .icon-required,ec-form-control.is-readonly .ec-form-control-clear,ec-form-control.is-disabled .icon-loading,ec-form-control.is-disabled .icon-invalid,ec-form-control.is-disabled .icon-required,ec-form-control.is-disabled .ec-form-control-clear{display:none}ec-form-control.is-readonly{border-color:var(--ec-form-control-border-color-readonly);color:var(--ec-form-control-color-readonly)}ec-form-control.is-readonly .ec-form-control-action{display:none}ec-form-control.is-disabled:not(.is-readonly){color:var(--ec-form-control-color-disabled);opacity:.6}ec-form-control.is-disabled:not(.is-readonly) .ec-form-control-prefix,ec-form-control.is-disabled:not(.is-readonly) .ec-form-control-suffix{color:inherit}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
3949
4806
|
}
|
3950
4807
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormControlComponent, decorators: [{
|
3951
4808
|
type: Component,
|
3952
|
-
args: [{ selector: 'ec-form-control', encapsulation: ViewEncapsulation.None, template: "<ng-content></ng-content>\r\n<i id=\"{{id + '_icon'}}\" class=\"ec-form-control-icon ec-icon {{icon}}\"></i>\r\n<i id=\"{{id + '_loading'}}\" class=\"ec-form-control-icon ec-icon icon-loading\"></i>\r\n<i id=\"{{id + '_required'}}\" class=\"ec-form-control-icon ec-icon icon-required\"></i>\r\n<i id=\"{{id + '_invalid'}}\" class=\"ec-form-control-icon ec-icon icon-invalid\"></i>\r\n<button *ngIf=\"showClear\"\r\n id=\"{{id + '_clear'}}\"\r\n [attr.disabled]=\"disabled || undefined\"\r\n class=\"ec-form-control-clear\"\r\n (click)=\"clear()\">\r\n <i class=\"ec-icon icon-cancel\"></i>\r\n</button>\r\n<button *ngIf=\"actionIcon\"\r\n id=\"{{id + '_action'}}\"\r\n [attr.disabled]=\"disabled || undefined\"\r\n class=\"ec-form-control-action\"\r\n (click)=\"actionClicked.emit($event)\"
|
4809
|
+
args: [{ selector: 'ec-form-control', encapsulation: ViewEncapsulation.None, template: "<ng-content></ng-content>\r\n<i id=\"{{id + '_icon'}}\" class=\"ec-form-control-icon ec-icon {{icon}}\"></i>\r\n<i id=\"{{id + '_loading'}}\" class=\"ec-form-control-icon ec-icon icon-loading\"></i>\r\n<i id=\"{{id + '_required'}}\" class=\"ec-form-control-icon ec-icon icon-required\"></i>\r\n<i id=\"{{id + '_invalid'}}\" class=\"ec-form-control-icon ec-icon icon-invalid\"></i>\r\n<button *ngIf=\"showClear\"\r\n id=\"{{id + '_clear'}}\"\r\n [attr.disabled]=\"disabled || undefined\"\r\n class=\"ec-form-control-clear\"\r\n (click)=\"clear()\">\r\n <i class=\"ec-icon icon-cancel\"></i>\r\n</button>\r\n<button *ngIf=\"actionIcon\"\r\n id=\"{{id + '_action'}}\"\r\n [attr.disabled]=\"disabled || undefined\"\r\n class=\"ec-form-control-action\"\r\n (click)=\"actionClicked.emit($event)\">\r\n <i class=\"ec-icon {{actionIcon}}\"></i>\r\n</button>\r\n<div class=\"ec-focus-ring\"></div>\r\n", styles: ["ec-form-control{background-color:var(--ec-form-control-background-color);background-clip:padding-box;border:1px solid var(--ec-form-control-border-color);border-radius:var(--ec-border-radius);padding:0 .5rem;position:relative;color:var(--ec-form-control-color);display:flex;font-size:var(--ec-form-control-font-size);min-height:2rem;width:100%}ec-form-control>input,ec-form-control>select,ec-form-control>textarea,ec-form-control>div[contenteditable=true]{color:inherit;flex:1 1;min-width:0;border:0;background-color:transparent;order:2}ec-form-control>input::selection,ec-form-control>select::selection,ec-form-control>textarea::selection,ec-form-control>div[contenteditable=true]::selection{background-color:var(--ec-form-control-background-color-selection);color:var(--ec-form-control-color-selection)}ec-form-control>input::-webkit-input-placeholder,ec-form-control>select::-webkit-input-placeholder,ec-form-control>textarea::-webkit-input-placeholder,ec-form-control>div[contenteditable=true]::-webkit-input-placeholder{color:var(--ec-form-control-color-placeholder)}ec-form-control>input::-moz-placeholder,ec-form-control>select::-moz-placeholder,ec-form-control>textarea::-moz-placeholder,ec-form-control>div[contenteditable=true]::-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}ec-form-control>input:-ms-input-placeholder,ec-form-control>select:-ms-input-placeholder,ec-form-control>textarea:-ms-input-placeholder,ec-form-control>div[contenteditable=true]:-ms-input-placeholder{color:var(--ec-form-control-color-placeholder)}ec-form-control>input:-moz-placeholder,ec-form-control>select:-moz-placeholder,ec-form-control>textarea:-moz-placeholder,ec-form-control>div[contenteditable=true]:-moz-placeholder{color:var(--ec-form-control-color-placeholder);opacity:1}ec-form-control>input:focus,ec-form-control>select:focus,ec-form-control>textarea:focus,ec-form-control>div[contenteditable=true]:focus{outline:none}ec-form-control>input:focus~.ec-focus-ring,ec-form-control>select:focus~.ec-focus-ring,ec-form-control>textarea:focus~.ec-focus-ring,ec-form-control>div[contenteditable=true]:focus~.ec-focus-ring{display:block}ec-form-control>input,ec-form-control>textarea,ec-form-control>select,ec-form-control>div[contenteditable=true],ec-form-control .ec-form-control-prefix,ec-form-control .ec-form-control-suffix{padding:calc((1.875rem - var(--ec-font-size-body) * 1.25) / 2) 0;line-height:1.25;font-size:inherit}ec-form-control>textarea{resize:none;padding:.3125rem 0}ec-form-control .ec-form-control-icon{margin-top:.4375rem;margin-right:.25rem;order:1}ec-form-control .ec-form-control-icon:not([class*=icon-]){display:none}ec-form-control .icon-required,ec-form-control .icon-invalid{color:var(--ec-form-control-border-color-invalid)}ec-form-control .ec-form-control-clear,ec-form-control .ec-form-control-action{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border-radius:var(--ec-border-radius);display:flex;cursor:pointer;flex:none;height:1.875rem;width:2rem;order:3;background-color:transparent;border:0;border-radius:0;display:inline-flex;align-items:center;justify-content:center;outline:none}ec-form-control .ec-form-control-clear .label,ec-form-control .ec-form-control-action .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}ec-form-control .ec-form-control-clear .ec-icon,ec-form-control .ec-form-control-action .ec-icon{flex:none}ec-form-control .ec-form-control-clear .ec-icon+.label,ec-form-control .ec-form-control-action .ec-icon+.label{flex:none;margin-left:.25rem}ec-form-control .ec-form-control-clear.has-badge,ec-form-control .ec-form-control-action.has-badge{padding-right:.0625rem}ec-form-control .ec-form-control-clear:focus,ec-form-control .ec-form-control-action:focus{outline:none;position:relative;z-index:1}ec-form-control .ec-form-control-clear:disabled,ec-form-control .ec-form-control-action:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}ec-form-control .ec-form-control-clear:disabled,ec-form-control .ec-form-control-action:disabled{border:0;background-color:transparent;border-color:transparent}ec-form-control .ec-form-control-clear:last-of-type,ec-form-control .ec-form-control-action:last-of-type{margin-right:-.5rem}ec-form-control .ec-form-control-clear:hover:not(:disabled),ec-form-control .ec-form-control-action:hover:not(:disabled){cursor:pointer;background-color:var(--ec-background-color-hover)}ec-form-control .ec-form-control-clear:active:not(:disabled),ec-form-control .ec-form-control-action:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}ec-form-control .ec-form-control-clear:focus:not(:disabled),ec-form-control .ec-form-control-action:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}ec-form-control button:last-of-type{border-top-right-radius:calc(var(--ec-form-control-border-radius) - .0625rem);border-bottom-right-radius:calc(var(--ec-form-control-border-radius) - .0625rem)}ec-form-control .ec-form-control-clear{width:1.5rem}ec-form-control .ec-form-control-prefix,ec-form-control .ec-form-control-suffix{color:var(--ec-color-secondary-dark);flex:none;cursor:default}ec-form-control .ec-form-control-prefix{margin-right:.125rem;order:2}ec-form-control .ec-form-control-suffix{margin-left:.125rem;order:3}ec-form-control .ec-focus-ring{position:absolute;inset:-1px;border:.125rem solid var(--ec-color-interactive);pointer-events:none;display:none;border-radius:var(--ec-form-control-border-radius);z-index:1}ec-form-control.is-pending .icon-invalid,ec-form-control.is-pending .icon-required{display:none}ec-form-control.is-invalid{border-color:var(--ec-form-control-border-color-invalid);background-color:var(--ec-form-control-background-color-invalid)}ec-form-control.is-invalid .icon-required{display:none}ec-form-control.is-empty .ec-form-control-clear{display:none}ec-form-control.is-required.is-empty .ec-form-control-icon:first-of-type{display:none}ec-form-control:not(.is-pending) .icon-loading{display:none}ec-form-control:not(.is-required) .icon-required,ec-form-control:not(.is-empty) .icon-required{display:none}ec-form-control:not(.is-invalid) .icon-invalid{display:none}ec-form-control.is-readonly,ec-form-control.is-disabled{background-color:var(--ec-form-control-background-color-disabled)}ec-form-control.is-readonly .icon-loading,ec-form-control.is-readonly .icon-invalid,ec-form-control.is-readonly .icon-required,ec-form-control.is-readonly .ec-form-control-clear,ec-form-control.is-disabled .icon-loading,ec-form-control.is-disabled .icon-invalid,ec-form-control.is-disabled .icon-required,ec-form-control.is-disabled .ec-form-control-clear{display:none}ec-form-control.is-readonly{border-color:var(--ec-form-control-border-color-readonly);color:var(--ec-form-control-color-readonly)}ec-form-control.is-readonly .ec-form-control-action{display:none}ec-form-control.is-disabled:not(.is-readonly){color:var(--ec-form-control-color-disabled);opacity:.6}ec-form-control.is-disabled:not(.is-readonly) .ec-form-control-prefix,ec-form-control.is-disabled:not(.is-readonly) .ec-form-control-suffix{color:inherit}\n"] }]
|
3953
4810
|
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { formControlDirective: [{
|
3954
4811
|
type: ContentChild,
|
3955
4812
|
args: [FormControlDirective]
|
@@ -3992,29 +4849,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
3992
4849
|
args: ['class.is-disabled']
|
3993
4850
|
}], actionClicked: [{
|
3994
4851
|
type: Output
|
3995
|
-
}], actionKeydown: [{
|
3996
|
-
type: Output
|
3997
4852
|
}], onClick: [{
|
3998
4853
|
type: HostListener,
|
3999
4854
|
args: ['click']
|
4000
4855
|
}] } });
|
4001
4856
|
|
4857
|
+
class LinkButtonComponent {
|
4858
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
4859
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LinkButtonComponent, selector: "button[ecLinkButton]", ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: [":host{display:inline;border:none;padding:0;background-color:transparent;font-size:inherit;text-align:start;color:var(--ec-color-link);cursor:pointer}:host:hover{text-decoration:underline}:host:focus{outline:none;text-decoration:underline}:host(:disabled){cursor:default;color:var(--ec-color-hint-dark)}:host(:disabled):hover{text-decoration:none}\n"] }); }
|
4860
|
+
}
|
4861
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkButtonComponent, decorators: [{
|
4862
|
+
type: Component,
|
4863
|
+
args: [{ selector: 'button[ecLinkButton]', template: `<ng-content></ng-content>`, styles: [":host{display:inline;border:none;padding:0;background-color:transparent;font-size:inherit;text-align:start;color:var(--ec-color-link);cursor:pointer}:host:hover{text-decoration:underline}:host:focus{outline:none;text-decoration:underline}:host(:disabled){cursor:default;color:var(--ec-color-hint-dark)}:host(:disabled):hover{text-decoration:none}\n"] }]
|
4864
|
+
}] });
|
4865
|
+
|
4866
|
+
/**
|
4867
|
+
* A basic helper directive to determine when focus leaves the host element.
|
4868
|
+
*
|
4869
|
+
* NOTE: This directive utilizes hidden anchor elements. These will disrupt tab order for elements
|
4870
|
+
* within a form. It is recommended to only use this directive when you need to redirect focus when
|
4871
|
+
* focus leaves a container. Also make sure this directive is disabled when the focus out events
|
4872
|
+
* are not needed to avoid keyboard nav problems.
|
4873
|
+
*/
|
4874
|
+
class KeyboardNavContainerDirective {
|
4875
|
+
constructor(hostEl, _document, interactivityChecker) {
|
4876
|
+
this.hostEl = hostEl;
|
4877
|
+
this._document = _document;
|
4878
|
+
this.interactivityChecker = interactivityChecker;
|
4879
|
+
this.enabled = true;
|
4880
|
+
this.focusOutStart = new EventEmitter();
|
4881
|
+
this.focusOutEnd = new EventEmitter();
|
4882
|
+
this.destroyed = new Subject();
|
4883
|
+
// Create the start and end anchors.
|
4884
|
+
this.startAnchor = this._document.createElement('div');
|
4885
|
+
this.endAnchor = this._document.createElement('div');
|
4886
|
+
// Hide the anchors from screen readers.
|
4887
|
+
this.startAnchor.setAttribute('aria-hidden', 'true');
|
4888
|
+
this.endAnchor.setAttribute('aria-hidden', 'true');
|
4889
|
+
}
|
4890
|
+
ngOnChanges() {
|
4891
|
+
this.toggleAnchors(this.enabled);
|
4892
|
+
}
|
4893
|
+
ngAfterViewInit() {
|
4894
|
+
// Insert the anchors into the DOM before and after the host element.
|
4895
|
+
this.hostEl.nativeElement.parentNode?.insertBefore(this.startAnchor, this.hostEl.nativeElement);
|
4896
|
+
this.hostEl.nativeElement.parentNode?.insertBefore(this.endAnchor, this.hostEl.nativeElement.nextSibling);
|
4897
|
+
// Listen for focus events on the anchors.
|
4898
|
+
fromEvent(this.startAnchor, 'focus').pipe(takeUntil(this.destroyed)).subscribe(() => this.focusOutStart.emit());
|
4899
|
+
fromEvent(this.endAnchor, 'focus').pipe(takeUntil(this.destroyed)).subscribe(() => this.focusOutEnd.emit());
|
4900
|
+
this.toggleAnchors(this.enabled);
|
4901
|
+
}
|
4902
|
+
ngOnDestroy() {
|
4903
|
+
this.destroyed.next();
|
4904
|
+
this.destroyed.complete();
|
4905
|
+
// Cleanup the anchors
|
4906
|
+
this.startAnchor.remove();
|
4907
|
+
this.endAnchor.remove();
|
4908
|
+
}
|
4909
|
+
focus() {
|
4910
|
+
const firstFocusableElement = this.getFirstFocusableElement(this.hostEl.nativeElement);
|
4911
|
+
firstFocusableElement?.focus();
|
4912
|
+
}
|
4913
|
+
getFirstFocusableElement(element) {
|
4914
|
+
// These are only possibly focusable. Some may be disabled or not visible.
|
4915
|
+
const elements = element.querySelectorAll('input, textarea, select, button, a, [tabindex], [contenteditable]');
|
4916
|
+
// Use the Angular CDK interactivity checker to determine if an element is actually focusable and tabbable.
|
4917
|
+
// This checks for disabledness among other things.
|
4918
|
+
const first = Array.from(elements).find(el => {
|
4919
|
+
return this.interactivityChecker.isFocusable(el) && this.interactivityChecker.isTabbable(el);
|
4920
|
+
});
|
4921
|
+
return first || null;
|
4922
|
+
}
|
4923
|
+
toggleAnchors(enabled) {
|
4924
|
+
// Make the anchors focusable if the container is enabled and we have subscribers for the events.
|
4925
|
+
// Otherwise, remove the tabindexes so they cannot receive focus and disrupt the tab order.
|
4926
|
+
if (enabled && this.focusOutStart.observers.length > 0) {
|
4927
|
+
this.startAnchor.setAttribute('tabindex', '0');
|
4928
|
+
}
|
4929
|
+
else {
|
4930
|
+
this.startAnchor.removeAttribute('tabindex');
|
4931
|
+
}
|
4932
|
+
if (enabled && this.focusOutEnd.observers.length > 0) {
|
4933
|
+
this.endAnchor.setAttribute('tabindex', '0');
|
4934
|
+
}
|
4935
|
+
else {
|
4936
|
+
this.endAnchor.removeAttribute('tabindex');
|
4937
|
+
}
|
4938
|
+
}
|
4939
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KeyboardNavContainerDirective, deps: [{ token: i0.ElementRef }, { token: DOCUMENT }, { token: i1$3.InteractivityChecker }], target: i0.ɵɵFactoryTarget.Directive }); }
|
4940
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: KeyboardNavContainerDirective, selector: "[ecKeyboardNavContainer]", inputs: { enabled: ["ecKeyboardNavContainer", "enabled"] }, outputs: { focusOutStart: "focusOutStart", focusOutEnd: "focusOutEnd" }, exportAs: ["ecKeyboardNavContainer"], usesOnChanges: true, ngImport: i0 }); }
|
4941
|
+
}
|
4942
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KeyboardNavContainerDirective, decorators: [{
|
4943
|
+
type: Directive,
|
4944
|
+
args: [{
|
4945
|
+
selector: '[ecKeyboardNavContainer]',
|
4946
|
+
exportAs: 'ecKeyboardNavContainer'
|
4947
|
+
}]
|
4948
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: Document, decorators: [{
|
4949
|
+
type: Inject,
|
4950
|
+
args: [DOCUMENT]
|
4951
|
+
}] }, { type: i1$3.InteractivityChecker }], propDecorators: { enabled: [{
|
4952
|
+
type: Input,
|
4953
|
+
args: ['ecKeyboardNavContainer']
|
4954
|
+
}], focusOutStart: [{
|
4955
|
+
type: Output
|
4956
|
+
}], focusOutEnd: [{
|
4957
|
+
type: Output
|
4958
|
+
}] } });
|
4959
|
+
|
4002
4960
|
class DateInputComponent extends FormControlBase {
|
4003
|
-
constructor(validationMessageService, formGroupHelper, userPreferenceService,
|
4961
|
+
constructor(validationMessageService, formGroupHelper, userPreferenceService, el, overlayService, selectionStrategies) {
|
4004
4962
|
super(validationMessageService, formGroupHelper);
|
4005
4963
|
this.validationMessageService = validationMessageService;
|
4006
4964
|
this.formGroupHelper = formGroupHelper;
|
4007
4965
|
this.userPreferenceService = userPreferenceService;
|
4008
|
-
this.dateDisplayPipe = dateDisplayPipe;
|
4009
4966
|
this.el = el;
|
4010
4967
|
this.overlayService = overlayService;
|
4968
|
+
this.selectionStrategies = selectionStrategies;
|
4011
4969
|
this.id = '';
|
4012
4970
|
/** The form control provided by the hosting form. */
|
4013
4971
|
this.formModel = new FormControl(null);
|
4014
4972
|
this.minDate = DateTimeHelper.minDatePickerDate;
|
4015
4973
|
this.maxDate = DateTimeHelper.maxDatePickerDate;
|
4016
|
-
/** The
|
4017
|
-
this.
|
4974
|
+
/** The initial selection mode for the calendar. Defaults to day if not provided */
|
4975
|
+
this.selectionMode = 'day';
|
4976
|
+
/** The available selection modes for the calendar. Defaults to only the initial selection mode if not provided. */
|
4977
|
+
this.selectionModeOptions = ['day'];
|
4978
|
+
/** Enables the next/previous selection buttons. */
|
4979
|
+
this.enableSteppers = false;
|
4980
|
+
/** The form group for the internal textboxes. Textbox2 is only used for ranges. */
|
4981
|
+
this.textboxGroup = new FormGroup({
|
4982
|
+
textbox: new FormControl(null),
|
4983
|
+
textbox2: new FormControl(null)
|
4984
|
+
});
|
4018
4985
|
/**
|
4019
4986
|
* The current calendar selection.
|
4020
4987
|
* Updated when the user clicks on a calendar item or when the date entered into the textbox is parsed.
|
@@ -4026,40 +4993,51 @@ class DateInputComponent extends FormControlBase {
|
|
4026
4993
|
this.placeholder = 'MM/DD/YYYY';
|
4027
4994
|
/** Overlay scroll strategy for the calendar overlay. Closes the calendar on scroll. */
|
4028
4995
|
this.overlayScrollStrategy = this.overlayService.scrollStrategies.close();
|
4996
|
+
this.primaryCalendarView = { mode: 'day', date: new Date() };
|
4997
|
+
this.secondaryCalendarView = { mode: 'day', date: new Date() };
|
4998
|
+
this.primaryCalendarMaxDate = DateTimeHelper.maxDatePickerDate;
|
4999
|
+
this.secondaryCalendarMinDate = DateTimeHelper.minDatePickerDate;
|
5000
|
+
this.disableSteppers = false;
|
4029
5001
|
/**
|
4030
5002
|
* Date parsing formats for user-entered dates. Defaults to month-first formats, but is updated in onInit
|
4031
5003
|
* to use the user's preferred date format.
|
4032
5004
|
*/
|
4033
|
-
this.parseFormats = DateTimeHelper.
|
4034
|
-
|
4035
|
-
|
4036
|
-
|
4037
|
-
|
4038
|
-
|
4039
|
-
|
4040
|
-
|
4041
|
-
|
4042
|
-
|
4043
|
-
|
4044
|
-
|
4045
|
-
|
4046
|
-
|
4047
|
-
|
4048
|
-
|
4049
|
-
|
5005
|
+
this.parseFormats = DateTimeHelper.getMomentParseFormats();
|
5006
|
+
}
|
5007
|
+
ngOnChanges(changes) {
|
5008
|
+
if (changes.selectionMode && !changes.selectionMode.isFirstChange()) {
|
5009
|
+
this.onSelectionModeChange(this.selectionMode);
|
5010
|
+
}
|
5011
|
+
}
|
5012
|
+
ngOnInit() {
|
5013
|
+
// Setup
|
5014
|
+
super.ngOnInit();
|
5015
|
+
this.setDateFormats();
|
5016
|
+
this.setSelectionMode(this.selectionMode);
|
5017
|
+
// Subscriptions
|
5018
|
+
this.onFormModelStatusChanges();
|
5019
|
+
this.onFormModelValueChanges();
|
5020
|
+
this.onTextboxValueChanges();
|
5021
|
+
// Sync the initial disabled status and value of the textbox
|
5022
|
+
this.syncTextboxControlDisabledStatus(this.formModel.status);
|
5023
|
+
const initialDisplayValue = this.selectionStrategy.formatSelection(this.formModel.value);
|
5024
|
+
this.textboxGroup.patchValue(initialDisplayValue, { emitEvent: false });
|
5025
|
+
// Update the calendar selection and view based on the initial form model value
|
5026
|
+
this.calendarSelection = this.formModel.value;
|
5027
|
+
this.updateCalendars(this.calendarSelection);
|
5028
|
+
this.updateSteppers(this.calendarSelection);
|
5029
|
+
console.log(this.calendarSelection);
|
4050
5030
|
}
|
4051
5031
|
/** Focuses the input whenever the calendar is shift-tabbed out of. */
|
4052
|
-
onCalendarFocusOutStart(
|
4053
|
-
event.preventDefault();
|
5032
|
+
onCalendarFocusOutStart() {
|
4054
5033
|
this.focusInput();
|
4055
5034
|
}
|
4056
5035
|
/** Closes the calendar and focuses the input whenever the calendar is tabbed out of. */
|
4057
|
-
onCalendarFocusOutEnd(
|
4058
|
-
event.preventDefault();
|
5036
|
+
onCalendarFocusOutEnd() {
|
4059
5037
|
this.isCalendarOpen = false;
|
4060
5038
|
this.focusInput();
|
4061
5039
|
}
|
4062
|
-
/**
|
5040
|
+
/** Closes the calendar if the user clicks outside of the calendar and date input. */
|
4063
5041
|
onOverlayOutsideClick(event) {
|
4064
5042
|
// Do not close the calendar if the click was within the date input or action button
|
4065
5043
|
const rect = this.el.nativeElement.getBoundingClientRect();
|
@@ -4070,74 +5048,107 @@ class DateInputComponent extends FormControlBase {
|
|
4070
5048
|
// It's possible that the user hit enter on the action button instead of clicking with the mouse.
|
4071
5049
|
// In this case the "click" event will be outside of the component because the clientx and y are 0,
|
4072
5050
|
// but we don't want to close in this case because button clicks trigger calendar open/close separately.
|
4073
|
-
const
|
5051
|
+
const targetId = event.target.id;
|
5052
|
+
const isActionClick = targetId === `${this.id}_action` || targetId === `${this.id}_control2_action`;
|
4074
5053
|
if (!isActionClick && clickedOutsideControl) {
|
4075
5054
|
this.isCalendarOpen = false;
|
4076
5055
|
}
|
4077
5056
|
}
|
4078
5057
|
/** If the user tabs out of the form control's action button and the calendar is open, focus the first item in the calendar overlay */
|
4079
|
-
|
4080
|
-
if (
|
4081
|
-
|
4082
|
-
event.preventDefault();
|
4083
|
-
// Focus the first button in the calendar overlay
|
4084
|
-
const firstButton = this.overlay?.overlayRef.hostElement.querySelector('button:not(:disabled)');
|
4085
|
-
firstButton?.focus();
|
5058
|
+
onControlsFocusOutEnd() {
|
5059
|
+
if (this.isCalendarOpen) {
|
5060
|
+
this.calendar?.focus();
|
4086
5061
|
}
|
4087
5062
|
}
|
4088
|
-
|
4089
|
-
|
4090
|
-
|
4091
|
-
|
4092
|
-
|
4093
|
-
|
4094
|
-
|
4095
|
-
|
4096
|
-
this.
|
4097
|
-
|
4098
|
-
|
5063
|
+
onTextboxBlur() {
|
5064
|
+
// We want to prevent the fixed date range modes from re-autocompleting the first textbox when it is explicitly cleared.
|
5065
|
+
const previousValue = DateInput.isSelectionRange(this.formModel.value) ? this.formModel.value.start : this.formModel.value;
|
5066
|
+
const currentValue = this.textboxGroup.value.textbox;
|
5067
|
+
const cleared = !!previousValue && !currentValue;
|
5068
|
+
const options = { preventAutoComplete: cleared };
|
5069
|
+
// Parse the textbox values into a selection and update the form model
|
5070
|
+
const parsedSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
5071
|
+
this.updateFormModel(parsedSelection);
|
5072
|
+
}
|
5073
|
+
onTextbox2Blur() {
|
5074
|
+
// We want to prevent the fixed date range modes from re-autocompleting the second textbox when it is explicitly cleared.
|
5075
|
+
const previousValue = DateInput.isSelectionRange(this.formModel.value) ? this.formModel.value.end : null;
|
5076
|
+
const currentValue = this.textboxGroup.value.textbox2;
|
5077
|
+
const cleared = !!previousValue && !currentValue;
|
5078
|
+
const options = { parseFromEnd: true, preventAutoComplete: cleared };
|
5079
|
+
// Parse the textbox values into a selection and update the form model,
|
5080
|
+
// For the second box we're keying the parse from the end date in the selection.
|
5081
|
+
const parsedSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
5082
|
+
this.updateFormModel(parsedSelection);
|
5083
|
+
}
|
5084
|
+
onSelectionModeChange(mode) {
|
5085
|
+
this.setSelectionMode(mode);
|
5086
|
+
const newSelection = this.selectionStrategy.getNewSelectionFromExisting(this.calendarSelection);
|
5087
|
+
this.updateFormModel(newSelection);
|
5088
|
+
// On selection mode change, we want to force the calendars to show the right view mode for the new selection.
|
5089
|
+
// This prevents the user from seeing a view mode that doesn't make sense for the new selection,
|
5090
|
+
// Like when swiching from year mode to last 7 days mode.
|
5091
|
+
this.primaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: this.primaryCalendarView.date };
|
5092
|
+
this.secondaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: this.secondaryCalendarView.date };
|
5093
|
+
this.updateCalendarMinMaxDates();
|
5094
|
+
}
|
5095
|
+
onCalendarDateSelected(date) {
|
5096
|
+
const newSelection = this.selectionStrategy.getSelectionFromDate(date, this.calendarSelection);
|
5097
|
+
const displayValue = this.selectionStrategy.formatSelection(newSelection);
|
5098
|
+
// Don't emit events when patching values here. We don't want to trigger the calendar updates since the calendar is already
|
5099
|
+
// showing the selected date. We also don't want to trigger the textbox parsing logic since the date was selected from the calendar.
|
5100
|
+
this.textboxGroup.patchValue(displayValue, { emitEvent: false });
|
5101
|
+
this.formModel.patchValue(newSelection, { emitEvent: false });
|
5102
|
+
this.calendarSelection = newSelection;
|
5103
|
+
this.updateSteppers(newSelection);
|
5104
|
+
// Close the calendar if the selection mode is not a range mode where either the start or the end date can be changed.
|
5105
|
+
if (!this.selectionStrategy.showSecondaryTextbox) {
|
4099
5106
|
this.isCalendarOpen = false;
|
4100
5107
|
this.focusInput();
|
4101
5108
|
}
|
4102
5109
|
}
|
4103
|
-
|
4104
|
-
|
4105
|
-
|
4106
|
-
|
4107
|
-
|
4108
|
-
|
4109
|
-
|
4110
|
-
|
4111
|
-
|
4112
|
-
|
4113
|
-
|
5110
|
+
onPrimaryCalendarViewChange(view) {
|
5111
|
+
this.primaryCalendarView = view;
|
5112
|
+
this.updateCalendarMinMaxDates();
|
5113
|
+
}
|
5114
|
+
onSecondaryCalendarViewChange(view) {
|
5115
|
+
this.secondaryCalendarView = view;
|
5116
|
+
this.updateCalendarMinMaxDates();
|
5117
|
+
}
|
5118
|
+
/** Shifts the calendar views to display today. Does not update the calendar selection. */
|
5119
|
+
goToToday() {
|
5120
|
+
// If both calendars are visible, show today in the secondary calendar and the month before in the primary calendar.
|
5121
|
+
if (this.selectionStrategy.showSecondaryCalendar) {
|
5122
|
+
this.primaryCalendarView = { mode: 'day', date: moment().subtract(1, 'month').toDate() };
|
5123
|
+
this.secondaryCalendarView = { mode: 'day', date: new Date() };
|
5124
|
+
// If we're in a single date mode, show today in the primary calendar.
|
4114
5125
|
}
|
4115
5126
|
else {
|
4116
|
-
this.
|
4117
|
-
}
|
4118
|
-
// Update the form model's touched and dirty status based on the textbox's status.
|
4119
|
-
// Since the user interacts with a control that is internal to this component, the
|
4120
|
-
// form model's status won't be updated automatically.
|
4121
|
-
if (this.textboxControl.touched && !this.formModel.touched) {
|
4122
|
-
this.formModel.markAsTouched();
|
5127
|
+
this.primaryCalendarView = { mode: 'day', date: new Date() };
|
4123
5128
|
}
|
4124
|
-
|
4125
|
-
|
5129
|
+
this.updateCalendarMinMaxDates();
|
5130
|
+
}
|
5131
|
+
goToQuickSelectDate() {
|
5132
|
+
if (this.quickSelectDate) {
|
5133
|
+
const newSelection = this.selectionStrategy.getSelectionForQuickSelectDate(this.quickSelectDate, this.calendarSelection);
|
5134
|
+
this.updateFormModel(newSelection);
|
4126
5135
|
}
|
4127
5136
|
}
|
4128
|
-
|
4129
|
-
|
4130
|
-
|
4131
|
-
|
4132
|
-
|
4133
|
-
|
4134
|
-
this.
|
4135
|
-
|
4136
|
-
|
4137
|
-
|
4138
|
-
|
4139
|
-
this
|
4140
|
-
|
5137
|
+
nextSelection() {
|
5138
|
+
const newSelection = this.selectionStrategy.getNextSelection(this.calendarSelection);
|
5139
|
+
this.updateFormModel(newSelection);
|
5140
|
+
}
|
5141
|
+
previousSelection() {
|
5142
|
+
const newSelection = this.selectionStrategy.getPreviousSelection(this.calendarSelection);
|
5143
|
+
this.updateFormModel(newSelection);
|
5144
|
+
}
|
5145
|
+
updateFormModel(value) {
|
5146
|
+
this.formModel.patchValue(value);
|
5147
|
+
// Validate the textboxes and sync the form errors
|
5148
|
+
// We do this after patching the form model because the form model patch will trigger
|
5149
|
+
// the date formatting logic and overwrite any errors on the controls from before.
|
5150
|
+
this.validateTextboxes();
|
5151
|
+
this.syncFormErrors();
|
4141
5152
|
}
|
4142
5153
|
onFormModelStatusChanges() {
|
4143
5154
|
// Keep the textboxControl disabled status in sync with the formModel
|
@@ -4155,12 +5166,13 @@ class DateInputComponent extends FormControlBase {
|
|
4155
5166
|
}
|
4156
5167
|
onFormModelValueChanges() {
|
4157
5168
|
// Update the calendar selection textbox value with a formatted date when the form model changes.
|
4158
|
-
// This is
|
4159
|
-
this.formModel.valueChanges.pipe(
|
4160
|
-
const displayValue = this.
|
5169
|
+
// This is triggered by the user selecting a date from the calendar or when the textbox is blurred.
|
5170
|
+
this.formModel.valueChanges.pipe(takeUntil(this.componentDestroyed)).subscribe(value => {
|
5171
|
+
const displayValue = this.selectionStrategy.formatSelection(value);
|
4161
5172
|
// Don't emit an event when setting the textbox value to avoid circular updates between the textbox and form model.
|
4162
|
-
this.
|
4163
|
-
this.
|
5173
|
+
this.textboxGroup.patchValue(displayValue, { emitEvent: false });
|
5174
|
+
this.updateCalendars(value);
|
5175
|
+
this.updateSteppers(value);
|
4164
5176
|
});
|
4165
5177
|
}
|
4166
5178
|
onTextboxValueChanges() {
|
@@ -4168,34 +5180,67 @@ class DateInputComponent extends FormControlBase {
|
|
4168
5180
|
// We don't patch the formModel here because we don't want to trigger the
|
4169
5181
|
// date formatting logic and overwrite the user's input.
|
4170
5182
|
// We'll do that when the user blurs out of the textbox. See onTextboxBlur()
|
4171
|
-
this.
|
4172
|
-
|
4173
|
-
|
4174
|
-
|
4175
|
-
|
4176
|
-
|
4177
|
-
|
4178
|
-
|
4179
|
-
}
|
4180
|
-
this.calendarSelection = parsedDate.toDate();
|
4181
|
-
}
|
5183
|
+
this.textboxGroup.controls.textbox.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(() => {
|
5184
|
+
const options = { shiftToCurrentYearIfBelow: this.minDate };
|
5185
|
+
const newSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
5186
|
+
// Calendar selection will be null if the dates are invalid. Don't update the calendars in this case.
|
5187
|
+
if (newSelection) {
|
5188
|
+
this.calendarSelection = newSelection;
|
5189
|
+
this.updatePrimaryCalendar(this.calendarSelection, this.selectionStrategy.showSecondaryCalendar);
|
5190
|
+
this.updateCalendarMinMaxDates();
|
4182
5191
|
}
|
4183
|
-
|
4184
|
-
|
5192
|
+
});
|
5193
|
+
// The second textbox is only used in last7Days, last28Days, and range modes.
|
5194
|
+
this.textboxGroup.controls.textbox2.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(() => {
|
5195
|
+
const options = { shiftToCurrentYearIfBelow: this.minDate, parseFromEnd: true };
|
5196
|
+
const newSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
5197
|
+
// Calendar selection will be null if the dates are invalid. Don't update the calendars in this case.
|
5198
|
+
if (newSelection) {
|
5199
|
+
this.calendarSelection = newSelection;
|
5200
|
+
// The secondary calendar is only shown in range mode. Update the primary calendar if we're not in range mode.
|
5201
|
+
if (this.selectionStrategy.showSecondaryCalendar) {
|
5202
|
+
this.updateSecondaryCalendar(this.calendarSelection, true);
|
5203
|
+
}
|
5204
|
+
else {
|
5205
|
+
this.updatePrimaryCalendar(this.calendarSelection);
|
5206
|
+
}
|
5207
|
+
this.updateCalendarMinMaxDates();
|
4185
5208
|
}
|
4186
5209
|
});
|
4187
5210
|
}
|
4188
5211
|
syncTextboxControlDisabledStatus(status) {
|
4189
5212
|
// The textbox should only be disabled if the form model is disabled.
|
4190
5213
|
// All other statuses are considered enabled.
|
4191
|
-
if (status === 'DISABLED' && this.
|
4192
|
-
this.
|
5214
|
+
if (status === 'DISABLED' && this.textboxGroup.enabled) {
|
5215
|
+
this.textboxGroup.disable();
|
4193
5216
|
}
|
4194
|
-
else if (status !== 'DISABLED' && this.
|
4195
|
-
this.
|
5217
|
+
else if (status !== 'DISABLED' && this.textboxGroup.disabled) {
|
5218
|
+
this.textboxGroup.enable();
|
4196
5219
|
}
|
4197
5220
|
}
|
4198
5221
|
;
|
5222
|
+
syncFormErrors() {
|
5223
|
+
// Start with the existing form model errors
|
5224
|
+
let errors = this.formModel.errors;
|
5225
|
+
// Add the errors from the textboxes if they exist
|
5226
|
+
if (this.textboxGroup.controls.textbox.errors) {
|
5227
|
+
errors = { ...errors, ...this.textboxGroup.controls.textbox.errors };
|
5228
|
+
}
|
5229
|
+
if (this.textboxGroup.controls.textbox2.errors) {
|
5230
|
+
errors = { ...errors, ...this.textboxGroup.controls.textbox2.errors };
|
5231
|
+
}
|
5232
|
+
// Update the form model's errors with the combined errors
|
5233
|
+
this.formModel.setErrors(errors);
|
5234
|
+
// Update the form model's touched and dirty status based on the textbox's status.
|
5235
|
+
// Since the user interacts with a control that is internal to this component, the
|
5236
|
+
// form model's status won't be updated automatically.
|
5237
|
+
if (this.textboxGroup.touched && !this.formModel.touched) {
|
5238
|
+
this.formModel.markAsTouched();
|
5239
|
+
}
|
5240
|
+
if (this.textboxGroup.dirty && !this.formModel.dirty) {
|
5241
|
+
this.formModel.markAsDirty();
|
5242
|
+
}
|
5243
|
+
}
|
4199
5244
|
/**
|
4200
5245
|
* Updates the date parsing formats and placeholder based on the user's display preference.
|
4201
5246
|
* NOTE: This is async because we're retrieving the user's preferences. We're not awaiting the result
|
@@ -4211,15 +5256,120 @@ class DateInputComponent extends FormControlBase {
|
|
4211
5256
|
}
|
4212
5257
|
/** Focuses the date input. */
|
4213
5258
|
focusInput() {
|
4214
|
-
this.
|
5259
|
+
this.controls?.focus();
|
5260
|
+
}
|
5261
|
+
setSelectionMode(mode) {
|
5262
|
+
this.selectionMode = mode;
|
5263
|
+
this.selectionStrategy = this.selectionStrategies[mode];
|
5264
|
+
}
|
5265
|
+
/**
|
5266
|
+
* Sets the max date for the primary calendar and the min date for the secondary calendar based
|
5267
|
+
* on the current views in each. This prevents the user from moving the calendars out of order.
|
5268
|
+
*/
|
5269
|
+
updateCalendarMinMaxDates() {
|
5270
|
+
// Only update the min/max dates when the view mode is 'day'.
|
5271
|
+
// When a calendar is in a month or year view mode, the view dates at the beginning of the year.
|
5272
|
+
// This would cause the dates in the other calendar to be unselectable if we were to
|
5273
|
+
// update the min/max dates in these cases.
|
5274
|
+
if (this.primaryCalendarView?.mode === 'day') {
|
5275
|
+
this.secondaryCalendarMinDate = moment(this.primaryCalendarView?.date).add(1, 'month').startOf('month').toDate();
|
5276
|
+
}
|
5277
|
+
if (this.secondaryCalendarView?.mode === 'day') {
|
5278
|
+
this.primaryCalendarMaxDate = moment(this.secondaryCalendarView?.date).subtract(1, 'month').endOf('month').toDate();
|
5279
|
+
}
|
5280
|
+
}
|
5281
|
+
updateCalendars(selection) {
|
5282
|
+
this.calendarSelection = selection;
|
5283
|
+
this.updatePrimaryCalendar(selection);
|
5284
|
+
// Only shift the primary calendar if we're showing the secondary calendar
|
5285
|
+
this.updateSecondaryCalendar(selection, this.selectionStrategy.showSecondaryCalendar);
|
5286
|
+
this.updateCalendarMinMaxDates();
|
5287
|
+
}
|
5288
|
+
updatePrimaryCalendar(selection, shiftSecondary = false) {
|
5289
|
+
this.primaryCalendarView = this.selectionStrategy.getPrimaryCalendarView(selection, this.minDate, this.maxDate, this.primaryCalendarView);
|
5290
|
+
// When entering a date into the first textbox, we really only want to update the primary calendar.
|
5291
|
+
// However, it's possible that the new date is after the secondary calendar's date. In this case,
|
5292
|
+
// We want to shift the secondary calendar so the calendars stay in order.
|
5293
|
+
if (shiftSecondary && this.secondaryCalendarView) {
|
5294
|
+
if (moment(this.primaryCalendarView.date).isSameOrAfter(this.secondaryCalendarView.date, 'month')) {
|
5295
|
+
let newSecondaryDate = moment(this.primaryCalendarView.date).add(1, 'month').toDate();
|
5296
|
+
this.secondaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: newSecondaryDate };
|
5297
|
+
}
|
5298
|
+
}
|
5299
|
+
}
|
5300
|
+
updateSecondaryCalendar(selection, shiftPrimary = false) {
|
5301
|
+
this.secondaryCalendarView = this.selectionStrategy.getSecondaryCalendarView(selection, this.minDate, this.maxDate, this.secondaryCalendarView);
|
5302
|
+
// When entering a date into the second textbox, we really only want to update the secondary calendar.
|
5303
|
+
// However, it's possible that the new date is before the primary calendar's date. In this case,
|
5304
|
+
// We want to shift the primary calendar so the calendars stay in order.
|
5305
|
+
if (shiftPrimary && this.primaryCalendarView) {
|
5306
|
+
if (moment(this.primaryCalendarView.date).isSameOrAfter(this.secondaryCalendarView.date, 'month')) {
|
5307
|
+
let newPrimaryDate = moment(this.secondaryCalendarView.date).subtract(1, 'month').toDate();
|
5308
|
+
this.primaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: newPrimaryDate };
|
5309
|
+
}
|
5310
|
+
}
|
5311
|
+
}
|
5312
|
+
updateSteppers(value) {
|
5313
|
+
// Disable the steppers if we either don't have a selection or only have one date in the selection.
|
5314
|
+
if (!value ||
|
5315
|
+
(DateInput.isSelectionSingleDate(value) && this.selectionMode !== 'day') ||
|
5316
|
+
(DateInput.isSelectionRange(value) && (!value.start || !value.end))) {
|
5317
|
+
this.disableSteppers = true;
|
5318
|
+
}
|
5319
|
+
else {
|
5320
|
+
this.disableSteppers = false;
|
5321
|
+
}
|
5322
|
+
}
|
5323
|
+
validateTextboxes() {
|
5324
|
+
const control = this.textboxGroup.controls.textbox;
|
5325
|
+
const control2 = this.textboxGroup.controls.textbox2;
|
5326
|
+
// The first textbox should only have the required error if it's empty and the date input is required,
|
5327
|
+
// or if the date input is not required and the second control is visible and has a value (meaning a partial range)
|
5328
|
+
if (!control.value &&
|
5329
|
+
(this.required || (control2.value && this.selectionStrategy.showSecondaryTextbox))) {
|
5330
|
+
control.setErrors({ required: true });
|
5331
|
+
}
|
5332
|
+
// The same idea applies to the second textbox, but only if it's visible
|
5333
|
+
if (this.selectionStrategy.showSecondaryTextbox &&
|
5334
|
+
!control2.value &&
|
5335
|
+
(this.required || control.value)) {
|
5336
|
+
control2.setErrors({ required: true });
|
5337
|
+
}
|
5338
|
+
if (control.value) {
|
5339
|
+
const errors = this.validateDateString(control.value);
|
5340
|
+
if (errors) {
|
5341
|
+
control.setErrors(errors);
|
5342
|
+
}
|
5343
|
+
}
|
5344
|
+
if (control2.value && this.selectionStrategy.showSecondaryTextbox) {
|
5345
|
+
const errors = this.validateDateString(control2.value);
|
5346
|
+
if (errors) {
|
5347
|
+
control2.setErrors(errors);
|
5348
|
+
}
|
5349
|
+
}
|
5350
|
+
}
|
5351
|
+
validateDateString(date) {
|
5352
|
+
const value = this.selectionStrategy.parseString(date, this.parseFormats);
|
5353
|
+
if (value) {
|
5354
|
+
// We're using the view mode as the granularity. We don't want to invalidate
|
5355
|
+
// the date in the case where you have a month/quarter/year selected and the min
|
5356
|
+
// or max date is somewhere within that month/quarter/year.
|
5357
|
+
if (moment(value).isBefore(this.minDate, this.selectionStrategy.selectionViewMode)) {
|
5358
|
+
return { minDate: { minValue: this.minDate } };
|
5359
|
+
}
|
5360
|
+
else if (moment(value).isAfter(this.maxDate, this.selectionStrategy.selectionViewMode)) {
|
5361
|
+
return { maxDate: { maxValue: this.maxDate } };
|
5362
|
+
}
|
5363
|
+
}
|
5364
|
+
return null;
|
4215
5365
|
}
|
4216
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateInputComponent, deps: [{ token: ValidationMessageService }, { token: FormGroupHelper }, { token: UserPreferenceService }, { token:
|
4217
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DateInputComponent, selector: "ec-date-input", inputs: { id: "id", formModel: "formModel", minDate: "minDate", maxDate: "maxDate" }, host: { properties: { "attr.id": "this.id" } }, viewQueries: [{ propertyName: "overlay", first: true, predicate: ["overlay"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<ec-form-control id=\"{{id}}\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n [formModel]=\"formModel\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n (actionKeydown)=\"onActionKeydown($event)\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n cdkOverlayOrigin\r\n #overlayOrigin=\"cdkOverlayOrigin\">\r\n <input id=\"{{id}}_input\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxControl\"\r\n (blur)=\"onTextboxBlur()\"\r\n (keydown)=\"onTextboxKeydown($event)\">\r\n</ec-form-control>\r\n\r\n<ng-template cdkConnectedOverlay\r\n #overlay=\"cdkConnectedOverlay\"\r\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\r\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\r\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\r\n cdkConnectedOverlayPanelClass=\"my-1\"\r\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\r\n (detach)=\"isCalendarOpen = false\">\r\n <ec-calendar [id]=\"id + '_calendar'\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [selection]=\"calendarSelection\"\r\n (selectionChange)=\"onSelectionChange($event)\"\r\n class=\"card px-1 pt-1 pb-2\"\r\n (focusOutStart)=\"onCalendarFocusOutStart($event)\"\r\n (focusOutEnd)=\"onCalendarFocusOutEnd($event)\">\r\n </ec-calendar>\r\n</ng-template>\r\n", styles: [":host{display:block}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "formModel", "autofocus", "pending", "required", "readonly"], outputs: ["actionClicked", "actionKeydown"] }, { kind: "component", type: HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "component", type: CalendarComponent, selector: "ec-calendar", inputs: ["id", "selection", "minDate", "maxDate"], outputs: ["selectionChange", "focusOutStart", "focusOutEnd"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] }); }
|
5366
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateInputComponent, deps: [{ token: ValidationMessageService }, { token: FormGroupHelper }, { token: UserPreferenceService }, { token: i0.ElementRef }, { token: i1$1.Overlay }, { token: DateInput.SelectionStrategies }], target: i0.ɵɵFactoryTarget.Component }); }
|
5367
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DateInputComponent, selector: "ec-date-input", inputs: { id: "id", formModel: "formModel", minDate: "minDate", maxDate: "maxDate", selectionMode: "selectionMode", selectionModeOptions: "selectionModeOptions", quickSelectDate: "quickSelectDate", enableSteppers: "enableSteppers" }, host: { properties: { "attr.id": "this.id" } }, providers: [DateInput.SelectionStrategies], viewQueries: [{ propertyName: "calendar", first: true, predicate: ["calendar"], descendants: true }, { propertyName: "controls", first: true, predicate: ["controls"], descendants: true }, { propertyName: "overlay", first: true, predicate: ["overlay"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<div class=\"d-flex align-items-center\"\r\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\r\n #controls=\"ecKeyboardNavContainer\"\r\n (focusOutEnd)=\"onControlsFocusOutEnd()\">\r\n <ec-form-control id=\"{{id}}\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n cdkOverlayOrigin\r\n #overlayOrigin=\"cdkOverlayOrigin\"\r\n class=\"flex-grow\"\r\n style=\"height: 2rem;\">\r\n <input id=\"{{id}}_input\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxGroup.get('textbox')\"\r\n (blur)=\"onTextboxBlur()\">\r\n </ec-form-control>\r\n\r\n <ng-container *ngIf=\"selectionStrategy.showSecondaryTextbox\">\r\n <span class=\"flex-shrink mx-1\">–</span>\r\n <ec-form-control id=\"{{id}}_control2\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n class=\"flex-grow\"\r\n style=\"height: 2rem;\">\r\n <input id=\"{{id}}_input2\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxGroup.get('textbox2')\"\r\n (blur)=\"onTextbox2Blur()\">\r\n </ec-form-control>\r\n </ng-container>\r\n\r\n <div *ngIf=\"enableSteppers\"\r\n class=\"control-group ml-2\">\r\n <ec-button id=\"{{id}}_previousSelection\"\r\n type=\"secondary\"\r\n icon=\"icon-angle-down rotate-90\"\r\n (clicked)=\"previousSelection()\"\r\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\">\r\n </ec-button>\r\n <ec-button id=\"{{id}}_nextSelection\"\r\n type=\"secondary\"\r\n icon=\"icon-angle-down rotate-270\"\r\n (clicked)=\"nextSelection()\"\r\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\">\r\n </ec-button>\r\n </div>\r\n\r\n <ec-button *ngIf=\"quickSelectDate\"\r\n id=\"{{id}}_quickSelect\"\r\n icon=\"icon-day\"\r\n type=\"secondary\"\r\n title=\"{{'DateInput_LatestDataAvailableTitle' | translate}}\"\r\n (clicked)=\"goToQuickSelectDate()\"\r\n class=\"ml-2\">\r\n </ec-button>\r\n</div>\r\n\r\n<ng-template cdkConnectedOverlay\r\n #overlay=\"cdkConnectedOverlay\"\r\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\r\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\r\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\r\n cdkConnectedOverlayPanelClass=\"my-1\"\r\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\r\n (detach)=\"isCalendarOpen = false\">\r\n <article id=\"{{id}}_datePicker\"\r\n class=\"card d-flex\"\r\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\r\n #calendar=\"ecKeyboardNavContainer\"\r\n (focusOutStart)=\"onCalendarFocusOutStart()\"\r\n (focusOutEnd)=\"onCalendarFocusOutEnd()\">\r\n <ul *ngIf=\"selectionModeOptions.length > 1\"\r\n class=\"selection-mode-menu border-right p-1\">\r\n <li *ngFor=\"let option of selectionModeOptions\">\r\n <button id=\"{{id}}_selectionMode_{{option}}\"\r\n class=\"text-body-1\"\r\n [class.is-selected]=\"option === selectionMode\"\r\n (click)=\"onSelectionModeChange(option)\">\r\n {{'DateInputSelectionMode_' + option | translate}}\r\n </button>\r\n </li>\r\n </ul>\r\n\r\n <div>\r\n <div class=\"d-flex\">\r\n <ec-calendar id=\"{{id}}_calendar\"\r\n [view]=\"primaryCalendarView\"\r\n (viewChange)=\"onPrimaryCalendarViewChange($event)\"\r\n [selectionMode]=\"selectionMode\"\r\n [selection]=\"calendarSelection\"\r\n (dateSelected)=\"onCalendarDateSelected($event)\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"selectionStrategy.showSecondaryCalendar ? primaryCalendarMaxDate : maxDate\">\r\n </ec-calendar>\r\n\r\n <ec-calendar *ngIf=\"selectionStrategy.showSecondaryCalendar\"\r\n id=\"{{id}}_secondaryCalendar\"\r\n [view]=\"secondaryCalendarView\"\r\n (viewChange)=\"onSecondaryCalendarViewChange($event)\"\r\n [selectionMode]=\"selectionMode\"\r\n [selection]=\"calendarSelection\"\r\n (dateSelected)=\"onCalendarDateSelected($event)\"\r\n [minDate]=\"secondaryCalendarMinDate\"\r\n [maxDate]=\"maxDate\">\r\n </ec-calendar>\r\n </div>\r\n\r\n <footer *ngIf=\"selectionStrategy.selectionViewMode === 'day'\"\r\n class=\"px-2 my-2 d-flex\">\r\n <button id=\"{{id}}_today_button\"\r\n ecLinkButton\r\n class=\"ml-auto d-inline-block\"\r\n (click)=\"goToToday()\"\r\n style=\"height: 1.75rem;\">\r\n {{'Today' | translate}}\r\n </button>\r\n </footer>\r\n </div>\r\n </article>\r\n</ng-template>\r\n", styles: [":host{display:block}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.date-picker{display:grid;grid-template-areas:\"menu calendar calendar\" \"menu footer footer\"}.date-picker footer{grid-area:footer}ul.selection-mode-menu{grid-area:menu;list-style:none;padding:0;margin:0;min-width:7rem}ul.selection-mode-menu li{margin-bottom:.25rem}ul.selection-mode-menu li button{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;width:100%;height:1.75rem}ul.selection-mode-menu li button .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}ul.selection-mode-menu li button .ec-icon{flex:none}ul.selection-mode-menu li button .ec-icon+.label{flex:none;margin-left:.25rem}ul.selection-mode-menu li button.has-badge{padding-right:.0625rem}ul.selection-mode-menu li button:focus{outline:none;position:relative;z-index:1}ul.selection-mode-menu li button:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}ul.selection-mode-menu li button:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}ul.selection-mode-menu li button:hover:not(:disabled){background-color:var(--ec-background-color-hover)}ul.selection-mode-menu li button:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}ul.selection-mode-menu li button:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}ul.selection-mode-menu li button.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}ec-button{--ec-button-border-color-secondary: var(--ec-border-color-control)}.control-group ec-button:has(+ec-button) ::ng-deep button{border-right:0}.control-group ec-button+ec-button ::ng-deep button{border-left:0}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "formModel", "autofocus", "pending", "required", "readonly"], outputs: ["actionClicked"] }, { kind: "component", type: HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "component", type: LinkButtonComponent, selector: "button[ecLinkButton]" }, { kind: "component", type: CalendarComponent, selector: "ec-calendar", inputs: ["id", "selection", "selectionMode", "minDate", "maxDate", "view"], outputs: ["dateSelected", "viewChange"] }, { kind: "directive", type: KeyboardNavContainerDirective, selector: "[ecKeyboardNavContainer]", inputs: ["ecKeyboardNavContainer"], outputs: ["focusOutStart", "focusOutEnd"], exportAs: ["ecKeyboardNavContainer"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] }); }
|
4218
5368
|
}
|
4219
5369
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateInputComponent, decorators: [{
|
4220
5370
|
type: Component,
|
4221
|
-
args: [{ selector: 'ec-date-input', template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<ec-form-control id=\"{{id}}\"\r\n
|
4222
|
-
}], ctorParameters: () => [{ type: ValidationMessageService }, { type: FormGroupHelper }, { type: UserPreferenceService }, { type:
|
5371
|
+
args: [{ selector: 'ec-date-input', providers: [DateInput.SelectionStrategies], template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<div class=\"d-flex align-items-center\"\r\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\r\n #controls=\"ecKeyboardNavContainer\"\r\n (focusOutEnd)=\"onControlsFocusOutEnd()\">\r\n <ec-form-control id=\"{{id}}\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n cdkOverlayOrigin\r\n #overlayOrigin=\"cdkOverlayOrigin\"\r\n class=\"flex-grow\"\r\n style=\"height: 2rem;\">\r\n <input id=\"{{id}}_input\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxGroup.get('textbox')\"\r\n (blur)=\"onTextboxBlur()\">\r\n </ec-form-control>\r\n\r\n <ng-container *ngIf=\"selectionStrategy.showSecondaryTextbox\">\r\n <span class=\"flex-shrink mx-1\">–</span>\r\n <ec-form-control id=\"{{id}}_control2\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n class=\"flex-grow\"\r\n style=\"height: 2rem;\">\r\n <input id=\"{{id}}_input2\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxGroup.get('textbox2')\"\r\n (blur)=\"onTextbox2Blur()\">\r\n </ec-form-control>\r\n </ng-container>\r\n\r\n <div *ngIf=\"enableSteppers\"\r\n class=\"control-group ml-2\">\r\n <ec-button id=\"{{id}}_previousSelection\"\r\n type=\"secondary\"\r\n icon=\"icon-angle-down rotate-90\"\r\n (clicked)=\"previousSelection()\"\r\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\">\r\n </ec-button>\r\n <ec-button id=\"{{id}}_nextSelection\"\r\n type=\"secondary\"\r\n icon=\"icon-angle-down rotate-270\"\r\n (clicked)=\"nextSelection()\"\r\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\">\r\n </ec-button>\r\n </div>\r\n\r\n <ec-button *ngIf=\"quickSelectDate\"\r\n id=\"{{id}}_quickSelect\"\r\n icon=\"icon-day\"\r\n type=\"secondary\"\r\n title=\"{{'DateInput_LatestDataAvailableTitle' | translate}}\"\r\n (clicked)=\"goToQuickSelectDate()\"\r\n class=\"ml-2\">\r\n </ec-button>\r\n</div>\r\n\r\n<ng-template cdkConnectedOverlay\r\n #overlay=\"cdkConnectedOverlay\"\r\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\r\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\r\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\r\n cdkConnectedOverlayPanelClass=\"my-1\"\r\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\r\n (detach)=\"isCalendarOpen = false\">\r\n <article id=\"{{id}}_datePicker\"\r\n class=\"card d-flex\"\r\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\r\n #calendar=\"ecKeyboardNavContainer\"\r\n (focusOutStart)=\"onCalendarFocusOutStart()\"\r\n (focusOutEnd)=\"onCalendarFocusOutEnd()\">\r\n <ul *ngIf=\"selectionModeOptions.length > 1\"\r\n class=\"selection-mode-menu border-right p-1\">\r\n <li *ngFor=\"let option of selectionModeOptions\">\r\n <button id=\"{{id}}_selectionMode_{{option}}\"\r\n class=\"text-body-1\"\r\n [class.is-selected]=\"option === selectionMode\"\r\n (click)=\"onSelectionModeChange(option)\">\r\n {{'DateInputSelectionMode_' + option | translate}}\r\n </button>\r\n </li>\r\n </ul>\r\n\r\n <div>\r\n <div class=\"d-flex\">\r\n <ec-calendar id=\"{{id}}_calendar\"\r\n [view]=\"primaryCalendarView\"\r\n (viewChange)=\"onPrimaryCalendarViewChange($event)\"\r\n [selectionMode]=\"selectionMode\"\r\n [selection]=\"calendarSelection\"\r\n (dateSelected)=\"onCalendarDateSelected($event)\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"selectionStrategy.showSecondaryCalendar ? primaryCalendarMaxDate : maxDate\">\r\n </ec-calendar>\r\n\r\n <ec-calendar *ngIf=\"selectionStrategy.showSecondaryCalendar\"\r\n id=\"{{id}}_secondaryCalendar\"\r\n [view]=\"secondaryCalendarView\"\r\n (viewChange)=\"onSecondaryCalendarViewChange($event)\"\r\n [selectionMode]=\"selectionMode\"\r\n [selection]=\"calendarSelection\"\r\n (dateSelected)=\"onCalendarDateSelected($event)\"\r\n [minDate]=\"secondaryCalendarMinDate\"\r\n [maxDate]=\"maxDate\">\r\n </ec-calendar>\r\n </div>\r\n\r\n <footer *ngIf=\"selectionStrategy.selectionViewMode === 'day'\"\r\n class=\"px-2 my-2 d-flex\">\r\n <button id=\"{{id}}_today_button\"\r\n ecLinkButton\r\n class=\"ml-auto d-inline-block\"\r\n (click)=\"goToToday()\"\r\n style=\"height: 1.75rem;\">\r\n {{'Today' | translate}}\r\n </button>\r\n </footer>\r\n </div>\r\n </article>\r\n</ng-template>\r\n", styles: [":host{display:block}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.date-picker{display:grid;grid-template-areas:\"menu calendar calendar\" \"menu footer footer\"}.date-picker footer{grid-area:footer}ul.selection-mode-menu{grid-area:menu;list-style:none;padding:0;margin:0;min-width:7rem}ul.selection-mode-menu li{margin-bottom:.25rem}ul.selection-mode-menu li button{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;width:100%;height:1.75rem}ul.selection-mode-menu li button .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}ul.selection-mode-menu li button .ec-icon{flex:none}ul.selection-mode-menu li button .ec-icon+.label{flex:none;margin-left:.25rem}ul.selection-mode-menu li button.has-badge{padding-right:.0625rem}ul.selection-mode-menu li button:focus{outline:none;position:relative;z-index:1}ul.selection-mode-menu li button:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}ul.selection-mode-menu li button:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}ul.selection-mode-menu li button:hover:not(:disabled){background-color:var(--ec-background-color-hover)}ul.selection-mode-menu li button:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}ul.selection-mode-menu li button:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}ul.selection-mode-menu li button.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}ec-button{--ec-button-border-color-secondary: var(--ec-border-color-control)}.control-group ec-button:has(+ec-button) ::ng-deep button{border-right:0}.control-group ec-button+ec-button ::ng-deep button{border-left:0}\n"] }]
|
5372
|
+
}], ctorParameters: () => [{ type: ValidationMessageService }, { type: FormGroupHelper }, { type: UserPreferenceService }, { type: i0.ElementRef }, { type: i1$1.Overlay }, { type: DateInput.SelectionStrategies }], propDecorators: { id: [{
|
4223
5373
|
type: HostBinding,
|
4224
5374
|
args: ['attr.id']
|
4225
5375
|
}, {
|
@@ -4230,6 +5380,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
4230
5380
|
type: Input
|
4231
5381
|
}], maxDate: [{
|
4232
5382
|
type: Input
|
5383
|
+
}], selectionMode: [{
|
5384
|
+
type: Input
|
5385
|
+
}], selectionModeOptions: [{
|
5386
|
+
type: Input
|
5387
|
+
}], quickSelectDate: [{
|
5388
|
+
type: Input
|
5389
|
+
}], enableSteppers: [{
|
5390
|
+
type: Input
|
5391
|
+
}], calendar: [{
|
5392
|
+
type: ViewChild,
|
5393
|
+
args: ['calendar']
|
5394
|
+
}], controls: [{
|
5395
|
+
type: ViewChild,
|
5396
|
+
args: ['controls']
|
4233
5397
|
}], overlay: [{
|
4234
5398
|
type: ViewChild,
|
4235
5399
|
args: ['overlay']
|
@@ -4931,7 +6095,7 @@ class FileUploadComponent extends FormControlBase {
|
|
4931
6095
|
}
|
4932
6096
|
}
|
4933
6097
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, deps: [{ token: ValidationMessageService }, { token: FormGroupHelper }], target: i0.ɵɵFactoryTarget.Component }); }
|
4934
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FileUploadComponent, selector: "ec-file-upload", inputs: { formModel: "formModel", placeholder: "placeholder", fileType: "fileType", fileOutput: "fileOutput", customExtensions: "customExtensions", onFileSelected: "onFileSelected", onMultipleFilesSelected: "onMultipleFilesSelected", displayType: "displayType", buttonLabel: "buttonLabel", buttonType: "buttonType", multiSelect: "multiSelect", validateBeforeUpload: "validateBeforeUpload" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ec-form-group [label]=\"label\"\r\n [formGroup]=\"formModel\"\r\n [helpPopover]=\"helpPopover\"\r\n [helpPopoverPosition]=\"helpPopoverPosition\"\r\n class=\"mb-0\">\r\n <div class=\"d-flex control-group\">\r\n <div class=\"d-flex flex-grow position-relative\">\r\n <input #fileInput\r\n id=\"{{inputId}}_input\"\r\n type=\"file\"\r\n tabindex=\"-1\"\r\n [attr.accept]=\"fileTypeAccept\"\r\n (change)=\"fileChange($event.target.files)\"\r\n [class.has-value]=\"displayType === 'file' ? formModel?.get('name').value : undefined\"\r\n [attr.multiple]=\"multiSelect ? 'multiple' : undefined\">\r\n <ec-form-control *ngIf=\"displayType === 'file'\"\r\n id=\"{{inputId}}_formControl\"\r\n class=\"text-truncate\"\r\n [required]=\"required\"\r\n [pending]=\"pending || formModel?.pending\">\r\n <input id=\"{{inputId}}_name\"\r\n [formControl]=\"formModel?.get('name')\"\r\n type=\"text\"\r\n [placeholder]=\"placeholder\"\r\n [tabindex]=\"-1\">\r\n </ec-form-control>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'file'\"\r\n #browseBtn\r\n id=\"{{inputId}}_browseBtn\"\r\n (clicked)=\"fileInput.click()\"\r\n type=\"secondary\"\r\n [tabindex]=\"tabindex\"\r\n [disabled]=\"formModel?.get('name').disabled\"\r\n label=\"Browse\"\r\n [autofocus]=\"autofocus\">\r\n </ec-button>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'button'\"\r\n id=\"{{inputId}}_btn\"\r\n [pending]=\"pending\"\r\n [type]=\"buttonType\"\r\n [label]=\"buttonLabel ?? 'Browse_TC' | translate\"\r\n (clicked)=\"fileInput.click()\"\r\n style=\"width: 100%;\">\r\n </ec-button>\r\n</ec-form-group>", styles: [":host{display:block;margin-bottom:1rem}ec-form-control{margin-bottom:0}ec-form-control ::ng-deep>.ec-focus-ring{display:none!important}input[type=file]{opacity:0;display:block;position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;cursor:pointer}input[type=file].has-value{width:calc(100% - 1.5rem)}ec-button{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "formModel", "autofocus", "pending", "required", "readonly"], outputs: ["actionClicked"
|
6098
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FileUploadComponent, selector: "ec-file-upload", inputs: { formModel: "formModel", placeholder: "placeholder", fileType: "fileType", fileOutput: "fileOutput", customExtensions: "customExtensions", onFileSelected: "onFileSelected", onMultipleFilesSelected: "onMultipleFilesSelected", displayType: "displayType", buttonLabel: "buttonLabel", buttonType: "buttonType", multiSelect: "multiSelect", validateBeforeUpload: "validateBeforeUpload" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ec-form-group [label]=\"label\"\r\n [formGroup]=\"formModel\"\r\n [helpPopover]=\"helpPopover\"\r\n [helpPopoverPosition]=\"helpPopoverPosition\"\r\n class=\"mb-0\">\r\n <div class=\"d-flex control-group\">\r\n <div class=\"d-flex flex-grow position-relative\">\r\n <input #fileInput\r\n id=\"{{inputId}}_input\"\r\n type=\"file\"\r\n tabindex=\"-1\"\r\n [attr.accept]=\"fileTypeAccept\"\r\n (change)=\"fileChange($event.target.files)\"\r\n [class.has-value]=\"displayType === 'file' ? formModel?.get('name').value : undefined\"\r\n [attr.multiple]=\"multiSelect ? 'multiple' : undefined\">\r\n <ec-form-control *ngIf=\"displayType === 'file'\"\r\n id=\"{{inputId}}_formControl\"\r\n class=\"text-truncate\"\r\n [required]=\"required\"\r\n [pending]=\"pending || formModel?.pending\">\r\n <input id=\"{{inputId}}_name\"\r\n [formControl]=\"formModel?.get('name')\"\r\n type=\"text\"\r\n [placeholder]=\"placeholder\"\r\n [tabindex]=\"-1\">\r\n </ec-form-control>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'file'\"\r\n #browseBtn\r\n id=\"{{inputId}}_browseBtn\"\r\n (clicked)=\"fileInput.click()\"\r\n type=\"secondary\"\r\n [tabindex]=\"tabindex\"\r\n [disabled]=\"formModel?.get('name').disabled\"\r\n label=\"Browse\"\r\n [autofocus]=\"autofocus\">\r\n </ec-button>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'button'\"\r\n id=\"{{inputId}}_btn\"\r\n [pending]=\"pending\"\r\n [type]=\"buttonType\"\r\n [label]=\"buttonLabel ?? 'Browse_TC' | translate\"\r\n (clicked)=\"fileInput.click()\"\r\n style=\"width: 100%;\">\r\n </ec-button>\r\n</ec-form-group>", styles: [":host{display:block;margin-bottom:1rem}ec-form-control{margin-bottom:0}ec-form-control ::ng-deep>.ec-focus-ring{display:none!important}input[type=file]{opacity:0;display:block;position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;cursor:pointer}input[type=file].has-value{width:calc(100% - 1.5rem)}ec-button{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "formModel", "autofocus", "pending", "required", "readonly"], outputs: ["actionClicked"] }, { kind: "component", type: FormGroupComponent, selector: "ec-form-group", inputs: ["id", "label", "formGroup", "labelPosition", "overrideValidationError", "hideValidationMessage", "helpPopover", "helpPopoverPosition"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] }); }
|
4935
6099
|
}
|
4936
6100
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, decorators: [{
|
4937
6101
|
type: Component,
|
@@ -5401,7 +6565,7 @@ class TableDetailRowComponent {
|
|
5401
6565
|
<td [class.has-max-height]="maxHeight" class="table-detail-content {{contentClass}}" [attr.colspan]="contentColSpan">
|
5402
6566
|
<div [style.max-height]="maxHeight" cdkScrollable><ng-content></ng-content></div>
|
5403
6567
|
</td>
|
5404
|
-
`, isInline: true, styles: [":host{background-color:var(--ec-background-color-detail)}td:first-child{width:1.5rem;padding:.25rem 0!important;vertical-align:top}.table-detail-content{background-color:transparent;border-top:1px solid var(--ec-border-color);padding:1rem 2rem 1rem 0!important}.table-detail-content.has-max-height{padding:0!important}.table-detail-content.has-max-height>div{overflow-y:auto;padding:1rem 2rem 1rem 0}\n"], dependencies: [{ kind: "directive", type: i1$
|
6568
|
+
`, isInline: true, styles: [":host{background-color:var(--ec-background-color-detail)}td:first-child{width:1.5rem;padding:.25rem 0!important;vertical-align:top}.table-detail-content{background-color:transparent;border-top:1px solid var(--ec-border-color);padding:1rem 2rem 1rem 0!important}.table-detail-content.has-max-height{padding:0!important}.table-detail-content.has-max-height>div{overflow-y:auto;padding:1rem 2rem 1rem 0}\n"], dependencies: [{ kind: "directive", type: i1$4.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }] }); }
|
5405
6569
|
}
|
5406
6570
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableDetailRowComponent, decorators: [{
|
5407
6571
|
type: Component,
|
@@ -6090,7 +7254,7 @@ class TableComponent {
|
|
6090
7254
|
});
|
6091
7255
|
}
|
6092
7256
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
6093
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TableComponent, selector: "ec-table", inputs: { id: "id", scrollable: "scrollable", resizable: "resizable", condensed: "condensed", sortable: "sortable", selectionContext: "selectionContext", selectionToolbarTemplate: "selectionToolbarTemplate", selectable: "selectable", isForm: "isForm", sort: "sort", searchableTableResizableColumns: ["resizableColumns", "searchableTableResizableColumns"] }, outputs: { sortChange: "sortChange" }, host: { properties: { "attr.id": "this.id", "class.is-scrollable": "this.scrollable", "class.is-resizable": "this.resizable", "class.is-condensed": "this.condensed", "class.is-sortable": "this.sortable", "class.is-selectable": "this.selectable", "class.is-form-table": "this.isForm", "class.is-master-detail": "this.hasMasterDetailRows" } }, queries: [{ propertyName: "masterRows", predicate: TableMasterRowComponent, descendants: true }, { propertyName: "_resizableColumns", predicate: ResizableColumnComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"selectable-table-toolbar\"\r\n *ngIf=\"hasSelection && selectionToolbarTemplate\">\r\n <ng-container *ngTemplateOutlet=\"selectionToolbarTemplate\"></ng-container>\r\n</div>\r\n<div id=\"{{id}}-scroll-container\" \r\n class=\"table-scroll-container\"\r\n cdkScrollable>\r\n <table class=\"main-table\"\r\n id=\"{{id}}\"\r\n [ecResizableTable]=\"resizable\"\r\n [containerEl]=\"el\"\r\n [sortableTable]=\"sortable\"\r\n [resizableColumns]=\"resizableColumns\">\r\n <ng-content></ng-content>\r\n </table>\r\n</div>", styles: ["ec-table{display:flex;position:relative;min-height:0}ec-table .table-scroll-container{flex:1 1;min-height:0;overflow-y:auto}ec-table .main-table{border-collapse:separate;border-spacing:0;width:100%;font-size:var(--ec-font-size-label)}ec-table .main-table th{height:2rem;line-height:1rem;padding:.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-bottom:1px solid var(--ec-border-color-dark);color:var(--ec-color-secondary-dark);font-weight:400;vertical-align:middle}ec-table .main-table th:first-child{padding-left:1rem}ec-table .main-table th:last-child{padding-right:1rem}ec-table .main-table td{height:2rem;line-height:1rem;padding:.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-top:1px solid var(--ec-border-color);vertical-align:top}ec-table .main-table td:first-child{padding-left:1rem}ec-table .main-table td:last-child{padding-right:1rem}ec-table .main-table tbody>tr:first-child td{border-top:0}ec-table .main-table tbody>tr.is-error td{background-color:var(--ec-background-color-danger)}ec-table .main-table tbody>tr.is-success td{background-color:var(--ec-background-color-success)}ec-table .main-table tfoot td{font-weight:700}ec-table .main-table tbody>tr.is-selected>td,ec-table .main-table tbody>tr.is-selected{background-color:var(--ec-background-color-selected)}ec-table .main-table tr.is-heading td{color:var(--ec-color-secondary-dark);font-size:var(--ec-font-size-label);font-weight:var(--ec-font-weight-bold);line-height:1.333333333;text-transform:uppercase;padding-bottom:0;vertical-align:bottom;border-top:0}ec-table .main-table tr.is-heading+tr td{border-top:0}ec-table .main-table th.actions-col,ec-table .main-table td.actions-col{padding:0}ec-table .main-table th.actions-1,ec-table .main-table td.actions-1{width:2.0625rem}ec-table .main-table th.actions-2,ec-table .main-table td.actions-2{width:4.0625rem}ec-table .main-table th.actions-3,ec-table .main-table td.actions-3{width:6.0625rem}ec-table .main-table th.actions-4,ec-table .main-table td.actions-4{width:8.0625rem}ec-table .main-table th.actions-5,ec-table .main-table td.actions-5{width:10.0625rem}ec-table.is-condensed th,ec-table.is-condensed td{padding-top:.25rem;padding-bottom:.25rem;height:1.5rem}ec-table.is-condensed:not(.has-borders)>table td{border-bottom-width:0;border-top-width:0}ec-table .selectable-table-toolbar{align-items:center;background-color:var(--ec-background-color);border-bottom:1px solid var(--ec-border-color-dark);display:flex;padding:0 .5rem;position:absolute;left:calc(var(--selection-toolbar-left, 0rem) + 1.625rem);top:0;height:3rem;right:0;z-index:calc(var(--ec-z-index-sticky-header) + 3)}ec-table.is-scrollable>.table-scroll-container>table{position:relative}ec-table.is-scrollable>.table-scroll-container>table>thead th{background-color:var(--ec-background-color);position:sticky!important;top:0;z-index:var(--ec-z-index-sticky-header)}ec-table.is-scrollable>.table-scroll-container>table>tfoot td{background-color:var(--ec-background-color);position:sticky!important;bottom:0;z-index:var(--ec-z-index-sticky-header)}ec-table.is-scrollable.bg-body>.table-scroll-container>table>thead th{background-color:var(--ec-background-color-body)}ec-table.is-scrollable.bg-body>.table-scroll-container>table>tfoot td{background-color:var(--ec-background-color-body)}ec-table.is-sortable th[data-sortfield]{-webkit-user-select:none;user-select:none}ec-table.is-sortable th[data-sortfield].is-resizable .content-wrapper{display:flex;cursor:pointer}ec-table.is-sortable th[data-sortfield].is-resizable .content{flex:0 1 auto}ec-table.is-sortable th[data-sortfield].is-resizable .content-wrapper:after{flex:none;width:.875rem;height:.875rem;margin:0 .25rem;font-size:.75rem;display:none;align-items:center;justify-content:center}ec-table.is-sortable th[data-sortfield].is-resizable.is-sorted-desc .content-wrapper:after,ec-table.is-sortable th[data-sortfield].is-resizable.is-sorted-asc .content-wrapper:after{font:var(--fa-font-solid);content:\"\\f062\";display:inline-flex}ec-table.is-sortable th[data-sortfield].is-resizable.is-sorted-desc .content-wrapper:after{transform:scaleY(-1)}ec-table.is-sortable th[data-sortfield].is-resizable.text-right .content-wrapper{flex-direction:row-reverse}ec-table.is-sortable th[data-sortfield]:not(.is-resizable){cursor:pointer}ec-table.is-sortable th[data-sortfield]:not(.is-resizable):after{width:.875rem;height:.875rem;margin:0 .25rem;font-size:.75rem;display:none;align-items:center;justify-content:center}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).is-sorted-desc:after,ec-table.is-sortable th[data-sortfield]:not(.is-resizable).is-sorted-asc:after{font:var(--fa-font-solid);content:\"\\f062\";display:inline-flex}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).is-sorted-desc:after{transform:scaleY(-1)}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right:after{content:\"\";display:none!important}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right:before{width:.875rem;height:.875rem;margin:0 .25rem;font-size:.75rem;display:none;align-items:center;justify-content:center}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right.is-sorted-desc:before,ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right.is-sorted-asc:before{font:var(--fa-font-solid);content:\"\\f062\";display:inline-block}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right.is-sorted-desc:before{transform:scaleY(-1)}ec-table.is-resizable .main-table{table-layout:fixed;width:100%}ec-table.is-resizable th.is-resizable{position:relative;overflow:visible;z-index:var(--ec-z-index-sticky-header)}ec-table.is-resizable th.is-resizable.is-active{-webkit-user-select:none;user-select:none}ec-table.is-resizable th.is-resizable.is-active .handle:after{background-color:var(--ec-color-interactive)}ec-table.is-resizable th.is-resizable .handle{position:absolute;width:13px;height:100%;top:0;padding:0 5px;z-index:var(--ec-z-index-splitter);right:0;padding:.5rem 0 .5rem 10px}ec-table.is-resizable th.is-resizable .handle:after{content:\"\";display:block;transition:background-color .3s ease;height:100%;position:relative}ec-table.is-resizable th.is-resizable .handle:hover{cursor:col-resize}ec-table.is-resizable th.is-resizable .handle:hover:after{background-color:var(--ec-color-interactive)}ec-table.is-resizable th.is-resizable .handle:before{content:\"\";display:block;width:1px;background-color:var(--ec-border-color);position:absolute;top:.5rem;bottom:.5rem;right:0}ec-table.is-resizable th.is-resizable .content{overflow:hidden;text-overflow:clip;white-space:nowrap}ec-table.is-resizable th.is-resizable:last-child .handle:before{display:none}ec-table.is-resizable td,ec-table.is-resizable th{overflow:hidden;text-overflow:clip;white-space:nowrap}ec-table.is-selectable .main-table thead th{height:3rem}ec-table.is-selectable .main-table tbody>tr:hover>td{background-color:var(--ec-background-color-hover);border-color:transparent;cursor:pointer}ec-table.is-selectable .main-table tbody>tr:hover.is-selected{background-color:var(--ec-background-color-selected)}ec-table.is-selectable .main-table tbody>tr:hover+tr>td{border-color:var(--ec-background-color-hover)}ec-table.is-selectable th.is-resizable .handle{padding-top:1rem;padding-bottom:1rem}ec-table.is-selectable th.is-resizable .handle:before{top:1rem;bottom:1rem}ec-table.is-master-detail>table{table-layout:fixed}ec-table.is-form-table td{padding-bottom:.25rem;padding-top:.25rem;height:2.5rem;line-height:2rem;border-top:0;font-size:var(--ec-font-size-body)}ec-table.is-form-table tr:first-child td{padding-top:.5rem;height:2.75rem}ec-table.is-form-table tr:last-child td{padding-bottom:.5rem;height:2.75rem}ec-table.is-fixed .main-table{table-layout:fixed}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$3.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: ResizableTableDirective, selector: "[ecResizableTable]", inputs: ["ecResizableTable", "containerEl", "sortableTable", "resizableColumns"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
7257
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TableComponent, selector: "ec-table", inputs: { id: "id", scrollable: "scrollable", resizable: "resizable", condensed: "condensed", sortable: "sortable", selectionContext: "selectionContext", selectionToolbarTemplate: "selectionToolbarTemplate", selectable: "selectable", isForm: "isForm", sort: "sort", searchableTableResizableColumns: ["resizableColumns", "searchableTableResizableColumns"] }, outputs: { sortChange: "sortChange" }, host: { properties: { "attr.id": "this.id", "class.is-scrollable": "this.scrollable", "class.is-resizable": "this.resizable", "class.is-condensed": "this.condensed", "class.is-sortable": "this.sortable", "class.is-selectable": "this.selectable", "class.is-form-table": "this.isForm", "class.is-master-detail": "this.hasMasterDetailRows" } }, queries: [{ propertyName: "masterRows", predicate: TableMasterRowComponent, descendants: true }, { propertyName: "_resizableColumns", predicate: ResizableColumnComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"selectable-table-toolbar\"\r\n *ngIf=\"hasSelection && selectionToolbarTemplate\">\r\n <ng-container *ngTemplateOutlet=\"selectionToolbarTemplate\"></ng-container>\r\n</div>\r\n<div id=\"{{id}}-scroll-container\" \r\n class=\"table-scroll-container\"\r\n cdkScrollable>\r\n <table class=\"main-table\"\r\n id=\"{{id}}\"\r\n [ecResizableTable]=\"resizable\"\r\n [containerEl]=\"el\"\r\n [sortableTable]=\"sortable\"\r\n [resizableColumns]=\"resizableColumns\">\r\n <ng-content></ng-content>\r\n </table>\r\n</div>", styles: ["ec-table{display:flex;position:relative;min-height:0}ec-table .table-scroll-container{flex:1 1;min-height:0;overflow-y:auto}ec-table .main-table{border-collapse:separate;border-spacing:0;width:100%;font-size:var(--ec-font-size-label)}ec-table .main-table th{height:2rem;line-height:1rem;padding:.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-bottom:1px solid var(--ec-border-color-dark);color:var(--ec-color-secondary-dark);font-weight:400;vertical-align:middle}ec-table .main-table th:first-child{padding-left:1rem}ec-table .main-table th:last-child{padding-right:1rem}ec-table .main-table td{height:2rem;line-height:1rem;padding:.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-top:1px solid var(--ec-border-color);vertical-align:top}ec-table .main-table td:first-child{padding-left:1rem}ec-table .main-table td:last-child{padding-right:1rem}ec-table .main-table tbody>tr:first-child td{border-top:0}ec-table .main-table tbody>tr.is-error td{background-color:var(--ec-background-color-danger)}ec-table .main-table tbody>tr.is-success td{background-color:var(--ec-background-color-success)}ec-table .main-table tfoot td{font-weight:700}ec-table .main-table tbody>tr.is-selected>td,ec-table .main-table tbody>tr.is-selected{background-color:var(--ec-background-color-selected)}ec-table .main-table tr.is-heading td{color:var(--ec-color-secondary-dark);font-size:var(--ec-font-size-label);font-weight:var(--ec-font-weight-bold);line-height:1.333333333;text-transform:uppercase;padding-bottom:0;vertical-align:bottom;border-top:0}ec-table .main-table tr.is-heading+tr td{border-top:0}ec-table .main-table th.actions-col,ec-table .main-table td.actions-col{padding:0}ec-table .main-table th.actions-1,ec-table .main-table td.actions-1{width:2.0625rem}ec-table .main-table th.actions-2,ec-table .main-table td.actions-2{width:4.0625rem}ec-table .main-table th.actions-3,ec-table .main-table td.actions-3{width:6.0625rem}ec-table .main-table th.actions-4,ec-table .main-table td.actions-4{width:8.0625rem}ec-table .main-table th.actions-5,ec-table .main-table td.actions-5{width:10.0625rem}ec-table.is-condensed th,ec-table.is-condensed td{padding-top:.25rem;padding-bottom:.25rem;height:1.5rem}ec-table.is-condensed:not(.has-borders)>table td{border-bottom-width:0;border-top-width:0}ec-table .selectable-table-toolbar{align-items:center;background-color:var(--ec-background-color);border-bottom:1px solid var(--ec-border-color-dark);display:flex;padding:0 .5rem;position:absolute;left:calc(var(--selection-toolbar-left, 0rem) + 1.625rem);top:0;height:3rem;right:0;z-index:calc(var(--ec-z-index-sticky-header) + 3)}ec-table.is-scrollable>.table-scroll-container>table{position:relative}ec-table.is-scrollable>.table-scroll-container>table>thead th{background-color:var(--ec-background-color);position:sticky!important;top:0;z-index:var(--ec-z-index-sticky-header)}ec-table.is-scrollable>.table-scroll-container>table>tfoot td{background-color:var(--ec-background-color);position:sticky!important;bottom:0;z-index:var(--ec-z-index-sticky-header)}ec-table.is-scrollable.bg-body>.table-scroll-container>table>thead th{background-color:var(--ec-background-color-body)}ec-table.is-scrollable.bg-body>.table-scroll-container>table>tfoot td{background-color:var(--ec-background-color-body)}ec-table.is-sortable th[data-sortfield]{-webkit-user-select:none;user-select:none}ec-table.is-sortable th[data-sortfield].is-resizable .content-wrapper{display:flex;cursor:pointer}ec-table.is-sortable th[data-sortfield].is-resizable .content{flex:0 1 auto}ec-table.is-sortable th[data-sortfield].is-resizable .content-wrapper:after{flex:none;width:.875rem;height:.875rem;margin:0 .25rem;font-size:.75rem;display:none;align-items:center;justify-content:center}ec-table.is-sortable th[data-sortfield].is-resizable.is-sorted-desc .content-wrapper:after,ec-table.is-sortable th[data-sortfield].is-resizable.is-sorted-asc .content-wrapper:after{font:var(--fa-font-solid);content:\"\\f062\";display:inline-flex}ec-table.is-sortable th[data-sortfield].is-resizable.is-sorted-desc .content-wrapper:after{transform:scaleY(-1)}ec-table.is-sortable th[data-sortfield].is-resizable.text-right .content-wrapper{flex-direction:row-reverse}ec-table.is-sortable th[data-sortfield]:not(.is-resizable){cursor:pointer}ec-table.is-sortable th[data-sortfield]:not(.is-resizable):after{width:.875rem;height:.875rem;margin:0 .25rem;font-size:.75rem;display:none;align-items:center;justify-content:center}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).is-sorted-desc:after,ec-table.is-sortable th[data-sortfield]:not(.is-resizable).is-sorted-asc:after{font:var(--fa-font-solid);content:\"\\f062\";display:inline-flex}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).is-sorted-desc:after{transform:scaleY(-1)}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right:after{content:\"\";display:none!important}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right:before{width:.875rem;height:.875rem;margin:0 .25rem;font-size:.75rem;display:none;align-items:center;justify-content:center}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right.is-sorted-desc:before,ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right.is-sorted-asc:before{font:var(--fa-font-solid);content:\"\\f062\";display:inline-block}ec-table.is-sortable th[data-sortfield]:not(.is-resizable).text-right.is-sorted-desc:before{transform:scaleY(-1)}ec-table.is-resizable .main-table{table-layout:fixed;width:100%}ec-table.is-resizable th.is-resizable{position:relative;overflow:visible;z-index:var(--ec-z-index-sticky-header)}ec-table.is-resizable th.is-resizable.is-active{-webkit-user-select:none;user-select:none}ec-table.is-resizable th.is-resizable.is-active .handle:after{background-color:var(--ec-color-interactive)}ec-table.is-resizable th.is-resizable .handle{position:absolute;width:13px;height:100%;top:0;padding:0 5px;z-index:var(--ec-z-index-splitter);right:0;padding:.5rem 0 .5rem 10px}ec-table.is-resizable th.is-resizable .handle:after{content:\"\";display:block;transition:background-color .3s ease;height:100%;position:relative}ec-table.is-resizable th.is-resizable .handle:hover{cursor:col-resize}ec-table.is-resizable th.is-resizable .handle:hover:after{background-color:var(--ec-color-interactive)}ec-table.is-resizable th.is-resizable .handle:before{content:\"\";display:block;width:1px;background-color:var(--ec-border-color);position:absolute;top:.5rem;bottom:.5rem;right:0}ec-table.is-resizable th.is-resizable .content{overflow:hidden;text-overflow:clip;white-space:nowrap}ec-table.is-resizable th.is-resizable:last-child .handle:before{display:none}ec-table.is-resizable td,ec-table.is-resizable th{overflow:hidden;text-overflow:clip;white-space:nowrap}ec-table.is-selectable .main-table thead th{height:3rem}ec-table.is-selectable .main-table tbody>tr:hover>td{background-color:var(--ec-background-color-hover);border-color:transparent;cursor:pointer}ec-table.is-selectable .main-table tbody>tr:hover.is-selected{background-color:var(--ec-background-color-selected)}ec-table.is-selectable .main-table tbody>tr:hover+tr>td{border-color:var(--ec-background-color-hover)}ec-table.is-selectable th.is-resizable .handle{padding-top:1rem;padding-bottom:1rem}ec-table.is-selectable th.is-resizable .handle:before{top:1rem;bottom:1rem}ec-table.is-master-detail>table{table-layout:fixed}ec-table.is-form-table td{padding-bottom:.25rem;padding-top:.25rem;height:2.5rem;line-height:2rem;border-top:0;font-size:var(--ec-font-size-body)}ec-table.is-form-table tr:first-child td{padding-top:.5rem;height:2.75rem}ec-table.is-form-table tr:last-child td{padding-bottom:.5rem;height:2.75rem}ec-table.is-fixed .main-table{table-layout:fixed}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$4.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: ResizableTableDirective, selector: "[ecResizableTable]", inputs: ["ecResizableTable", "containerEl", "sortableTable", "resizableColumns"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
6094
7258
|
}
|
6095
7259
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TableComponent, decorators: [{
|
6096
7260
|
type: Component,
|
@@ -6806,19 +7970,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
6806
7970
|
}], overlayClasses: [{
|
6807
7971
|
type: Input
|
6808
7972
|
}], fillParentHeight: [{
|
6809
|
-
type: Input
|
6810
|
-
}], disablePaginationControls: [{
|
6811
|
-
type: Input
|
6812
|
-
}] } });
|
6813
|
-
|
6814
|
-
class LinkButtonComponent {
|
6815
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
6816
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LinkButtonComponent, selector: "button[ecLinkButton]", ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: [":host{display:inline;border:none;padding:0;background-color:transparent;font-size:inherit;text-align:start;color:var(--ec-color-link);cursor:pointer}:host:hover{text-decoration:underline}:host:focus{outline:none;text-decoration:underline}:host(:disabled){cursor:default;color:var(--ec-color-hint-dark)}:host(:disabled):hover{text-decoration:none}\n"] }); }
|
6817
|
-
}
|
6818
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LinkButtonComponent, decorators: [{
|
6819
|
-
type: Component,
|
6820
|
-
args: [{ selector: 'button[ecLinkButton]', template: `<ng-content></ng-content>`, styles: [":host{display:inline;border:none;padding:0;background-color:transparent;font-size:inherit;text-align:start;color:var(--ec-color-link);cursor:pointer}:host:hover{text-decoration:underline}:host:focus{outline:none;text-decoration:underline}:host(:disabled){cursor:default;color:var(--ec-color-hint-dark)}:host(:disabled):hover{text-decoration:none}\n"] }]
|
6821
|
-
}] });
|
7973
|
+
type: Input
|
7974
|
+
}], disablePaginationControls: [{
|
7975
|
+
type: Input
|
7976
|
+
}] } });
|
6822
7977
|
|
6823
7978
|
;
|
6824
7979
|
class ItemPickerSelectableContext extends TableSelectableRowContext {
|
@@ -8352,7 +9507,7 @@ class DialogComponent {
|
|
8352
9507
|
return this.componentRef?.instance.dialogId || '';
|
8353
9508
|
}
|
8354
9509
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DialogComponent, deps: [{ token: i0.ComponentFactoryResolver }, { token: WindowService }, { token: DialogService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
|
8355
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DialogComponent, selector: "ec-dialog", inputs: { size: "size", content: "content", context: "context", options: "options", dialogOpenStartEventId: "dialogOpenStartEventId" }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "click": "onOverlayClick($event)" }, properties: { "class": "dialogSizeClass", "style.--ec-dialog-width.px": "width", "class.is-open": "this.isOpen", "class.fade-in": "this.fadeIn", "class.fade-out": "this.fadeOut", "class.is-panel": "this.displayAsPanel", "class.is-top-aligned": "this.alignToTop", "style.--ec-dialog-margin-align-to-top": "this.alignToTopMargin", "class.is-transparent": "this.transparentMask", "class.no-mask": "this.noMask" } }, viewQueries: [{ propertyName: "contentContainer", first: true, predicate: ["content"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: '<article [style.min-width]="minWidth" cdkTrapFocus cdkTrapFocusAutoCapture><ng-template #content></ng-template></article>', isInline: true, styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes panelMaskFadeIn{0%{background-color:transparent}to{background-color:var(--ec-dialog-background-color)}}:host{--ec-dialog-background-color: var(--ec-background-color-dialog);align-items:center;background-color:var(--ec-dialog-background-color);justify-content:center;position:fixed;z-index:var(--ec-z-index-dialog);inset:0;display:none}:host.is-open{display:flex}:host.fade-in{animation-name:fadeIn;animation-duration:125ms;animation-fill-mode:forwards;animation-timing-function:ease-in-out}:host.fade-out{animation-name:fadeIn;animation-duration:.1s;animation-direction:reverse;animation-fill-mode:forwards;animation-timing-function:ease-in-out}:host.is-panel article{position:absolute;top:0;bottom:0;right:0;max-height:none;border-right:0;border-top:0;border-bottom:0;border-radius:0;box-shadow:0 0 .5rem var(--ec-color-shadow)}:host.is-panel.fade-in{animation-name:panelMaskFadeIn;animation-duration:.25s;animation-fill-mode:forwards}:host.is-panel.fade-in article{animation-name:slideIn;animation-duration:.25s;animation-fill-mode:forwards;animation-timing-function:ease-out}:host.is-panel.fade-out{animation-name:panelMaskFadeIn;animation-direction:reverse;animation-fill-mode:forwards}:host.is-panel.fade-out article{animation-name:slideIn;animation-duration:225ms;animation-direction:reverse;animation-fill-mode:forwards;animation-timing-function:ease-in}:host.is-panel.no-mask{left:auto;width:var(--ec-dialog-width)}:host.is-top-aligned{align-items:flex-start}:host.is-top-aligned article{min-height:auto;margin-top:var(--ec-dialog-margin-align-to-top, 20vh);max-height:calc(100vh - var(--ec-dialog-margin-align-to-top, 20vh) - 5vh)}:host.is-transparent{--ec-dialog-background-color: transparent}article{background-color:var(--ec-background-color-body);background-clip:padding-box;box-shadow:0 0 .625rem #1a1a2333;border-radius:var(--ec-border-radius-dialog);overflow:hidden;display:flex;flex:none;min-height:9rem;max-height:90vh;max-width:90vw;width:var(--ec-dialog-width)}:host.dialog-xsmall{--ec-dialog-width: 20rem}:host.dialog-small{--ec-dialog-width: 30rem}:host.dialog-medium{--ec-dialog-width: 40rem}:host.dialog-large{--ec-dialog-width: 50rem}:host.dialog-xlarge{--ec-dialog-width: 60rem}:host.dialog-full{--ec-dialog-width: 90vw}\n"], dependencies: [{ kind: "directive", type:
|
9510
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DialogComponent, selector: "ec-dialog", inputs: { size: "size", content: "content", context: "context", options: "options", dialogOpenStartEventId: "dialogOpenStartEventId" }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "click": "onOverlayClick($event)" }, properties: { "class": "dialogSizeClass", "style.--ec-dialog-width.px": "width", "class.is-open": "this.isOpen", "class.fade-in": "this.fadeIn", "class.fade-out": "this.fadeOut", "class.is-panel": "this.displayAsPanel", "class.is-top-aligned": "this.alignToTop", "style.--ec-dialog-margin-align-to-top": "this.alignToTopMargin", "class.is-transparent": "this.transparentMask", "class.no-mask": "this.noMask" } }, viewQueries: [{ propertyName: "contentContainer", first: true, predicate: ["content"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: '<article [style.min-width]="minWidth" cdkTrapFocus cdkTrapFocusAutoCapture><ng-template #content></ng-template></article>', isInline: true, styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes panelMaskFadeIn{0%{background-color:transparent}to{background-color:var(--ec-dialog-background-color)}}:host{--ec-dialog-background-color: var(--ec-background-color-dialog);align-items:center;background-color:var(--ec-dialog-background-color);justify-content:center;position:fixed;z-index:var(--ec-z-index-dialog);inset:0;display:none}:host.is-open{display:flex}:host.fade-in{animation-name:fadeIn;animation-duration:125ms;animation-fill-mode:forwards;animation-timing-function:ease-in-out}:host.fade-out{animation-name:fadeIn;animation-duration:.1s;animation-direction:reverse;animation-fill-mode:forwards;animation-timing-function:ease-in-out}:host.is-panel article{position:absolute;top:0;bottom:0;right:0;max-height:none;border-right:0;border-top:0;border-bottom:0;border-radius:0;box-shadow:0 0 .5rem var(--ec-color-shadow)}:host.is-panel.fade-in{animation-name:panelMaskFadeIn;animation-duration:.25s;animation-fill-mode:forwards}:host.is-panel.fade-in article{animation-name:slideIn;animation-duration:.25s;animation-fill-mode:forwards;animation-timing-function:ease-out}:host.is-panel.fade-out{animation-name:panelMaskFadeIn;animation-direction:reverse;animation-fill-mode:forwards}:host.is-panel.fade-out article{animation-name:slideIn;animation-duration:225ms;animation-direction:reverse;animation-fill-mode:forwards;animation-timing-function:ease-in}:host.is-panel.no-mask{left:auto;width:var(--ec-dialog-width)}:host.is-top-aligned{align-items:flex-start}:host.is-top-aligned article{min-height:auto;margin-top:var(--ec-dialog-margin-align-to-top, 20vh);max-height:calc(100vh - var(--ec-dialog-margin-align-to-top, 20vh) - 5vh)}:host.is-transparent{--ec-dialog-background-color: transparent}article{background-color:var(--ec-background-color-body);background-clip:padding-box;box-shadow:0 0 .625rem #1a1a2333;border-radius:var(--ec-border-radius-dialog);overflow:hidden;display:flex;flex:none;min-height:9rem;max-height:90vh;max-width:90vw;width:var(--ec-dialog-width)}:host.dialog-xsmall{--ec-dialog-width: 20rem}:host.dialog-small{--ec-dialog-width: 30rem}:host.dialog-medium{--ec-dialog-width: 40rem}:host.dialog-large{--ec-dialog-width: 50rem}:host.dialog-xlarge{--ec-dialog-width: 60rem}:host.dialog-full{--ec-dialog-width: 90vw}\n"], dependencies: [{ kind: "directive", type: i1$3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }] }); }
|
8356
9511
|
}
|
8357
9512
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DialogComponent, decorators: [{
|
8358
9513
|
type: Component,
|
@@ -10274,7 +11429,7 @@ class PageViewComponent {
|
|
10274
11429
|
this.dialogService.closeLatestDialog(new DialogResult(false));
|
10275
11430
|
}
|
10276
11431
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PageViewComponent, deps: [{ token: DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
|
10277
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PageViewComponent, selector: "ec-page-view", inputs: { isDialog: "isDialog", readonly: "readonly", status: "status", showHeader: "showHeader", errors: "errors", breadcrumbs: "breadcrumbs", title: "title", titleIcon: "titleIcon", subTitle: "subTitle", subTitleUrl: "subTitleUrl", moreActionsLabel: "moreActionsLabel", moreActions: "moreActions", secondaryActionLabel: "secondaryActionLabel", hideSecondaryAction: "hideSecondaryAction", hideCloseOnPending: "hideCloseOnPending", primaryActionLabel: "primaryActionLabel", hidePrimaryAction: "hidePrimaryAction", customTitleTemplate: "customTitleTemplate", customActionsTemplate: "customActionsTemplate", customHeaderTemplate: "customHeaderTemplate", footerTemplate: "footerTemplate", customErrorBannerTemplate: "customErrorBannerTemplate", stickyFooter: "stickyFooter", fitContent: "fitContent", disablePrimaryAction: "disablePrimaryAction", bgContent: "bgContent" }, outputs: { onPrimaryAction: "onPrimaryAction", onSecondaryAction: "onSecondaryAction" }, host: { properties: { "class.bg-content": "this.bgContent" }, classAttribute: "flex-grow" }, ngImport: i0, template: "<div ecOverlay\r\n [status]=\"status?.status\"\r\n [message]=\"status?.message\"\r\n [displayAsMask]=\"true\"\r\n class=\"flex-grow d-flex\"\r\n [ngClass]=\"{'bg-body': !bgContent, 'bg-content': bgContent}\">\r\n <div id=\"PageViewScrollContainer\"\r\n class=\"d-flex flex-column flex-grow scroll-y\"\r\n [class.is-dialog]=\"isDialog\"\r\n [class.fit-content]=\"fitContent\"\r\n [class.sticky-footer]=\"stickyFooter && !!footerTemplate\"\r\n [class.overlay-visible]=\"status?.status !== 'hasData'\"\r\n [class.footer-visible]=\"!!footerTemplate\"\r\n cdkScrollable>\r\n <section>\r\n <ng-content></ng-content>\r\n </section>\r\n\r\n <footer *ngIf=\"footerTemplate\">\r\n <ng-container *ngTemplateOutlet=\"footerTemplate\"></ng-container>\r\n </footer>\r\n\r\n <header *ngIf=\"showHeader\">\r\n <ol id=\"breadcrumbs\"\r\n *ngIf=\"breadcrumbs?.length && !isDialog\">\r\n <li *ngFor=\"let crumb of breadcrumbs; last as isLast\">\r\n <a *ngIf=\"crumb.url; else label\"\r\n [routerLink]=\"crumb.url\">\r\n <ng-container *ngTemplateOutlet=\"label\"></ng-container>\r\n </a>\r\n <ng-template #label>{{crumb.label}}</ng-template>\r\n </li>\r\n </ol>\r\n\r\n <div class=\"titlebar\">\r\n <app-page-title *ngIf=\"!customTitleTemplate; else customTitle\"\r\n [title]=\"title\"\r\n [subTitle]=\"subTitle\"\r\n [subTitleUrl]=\"subTitleUrl\"\r\n [titleIcon]=\"titleIcon\"\r\n class=\"title text-truncate\">\r\n </app-page-title>\r\n\r\n <ng-template #customTitle>\r\n <div class=\"title\">\r\n <ng-container *ngTemplateOutlet=\"customTitleTemplate\"></ng-container>\r\n </div>\r\n </ng-template>\r\n\r\n <div class=\"actions\">\r\n <ec-button id=\"primaryAction\"\r\n class=\"ml-2\"\r\n *ngIf=\"!hidePrimaryAction && onPrimaryAction.observers?.length && !readonly\"\r\n [disabled]=\"status?.status === 'pending' || disablePrimaryAction\"\r\n type=\"primary\"\r\n [label]=\"primaryActionLabel\"\r\n (clicked)=\"primaryAction($event)\">\r\n </ec-button>\r\n <ec-button id=\"secondaryAction\"\r\n class=\"ml-2\"\r\n *ngIf=\"!hideSecondaryAction && onSecondaryAction.observers?.length\"\r\n type=\"secondary\"\r\n [label]=\"readonly ? 'Close' : secondaryActionLabel\"\r\n (clicked)=\"secondaryAction($event)\">\r\n </ec-button>\r\n <ec-dropdown id=\"moreActions\"\r\n *ngIf=\"moreActions?.length && !readonly\"\r\n [disabled]=\"status?.status === 'pending'\"\r\n class=\"ml-2\"\r\n buttonType=\"text\"\r\n [label]=\"moreActionsLabel\"\r\n [items]=\"moreActions\">\r\n </ec-dropdown>\r\n <ng-container *ngTemplateOutlet=\"customActionsTemplate\"></ng-container>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"customHeaderTemplate\"\r\n class=\"page-header\">\r\n <ng-container *ngTemplateOutlet=\"customHeaderTemplate\"></ng-container>\r\n </div>\r\n\r\n <ec-banner *ngIf=\"!customErrorBannerTemplate && errors; else customErrorBannerOutlet\"\r\n id=\"pageViewErrors\"\r\n [class.border-bottom-0]=\"!isDialog\">\r\n <div [innerHtml]=\"errors\"></div>\r\n </ec-banner>\r\n\r\n <ng-template #customErrorBannerOutlet>\r\n <ec-banner *ngIf=\"errors\"\r\n id=\"pageViewErrors\"\r\n [class.border-bottom-0]=\"!isDialog\">\r\n <ng-container *ngTemplateOutlet=\"customErrorBannerTemplate\"></ng-container>\r\n </ec-banner>\r\n </ng-template>\r\n </header>\r\n </div>\r\n\r\n <ec-button *ngIf=\"isDialog && ( (status?.status === 'pending' && !hideCloseOnPending) || status?.status === 'error')\"\r\n id=\"pageViewDialogClose\"\r\n type=\"icon\"\r\n icon=\"icon-cancel\"\r\n (clicked)=\"closeDialog()\">\r\n </ec-button>\r\n</div>", styles: [":host{flex:1 1;min-height:0;display:flex}header{background-color:var(--ec-background-color-body);position:sticky;top:0;order:1;padding:1rem 1.5rem .5rem;flex:none;z-index:var(--ec-z-index-sticky-page-header)}ol{font-size:var(--ec-font-size-label);line-height:1rem;grid-column:1/3;grid-row:1/2;list-style:none;padding:0;margin:0 0 .25rem}ol li{display:inline}ol li:not(:last-child):after{content:\" / \";display:inline;color:var(--ec-color-secondary-dark)}div[ecOverlay]{position:relative}.titlebar{display:grid;grid-template-columns:auto max-content;grid-template-rows:max-content max-content;gap:0 1rem}.title{grid-column:1/2;grid-row:2/3;align-self:center}.actions{grid-column:2/3;grid-row:2/3;display:flex;flex-direction:row-reverse}ec-banner{margin-top:1rem}section{padding:var(--ec-page-view-padding-section, .5rem 1.5rem 2rem);order:2;flex:1 0 auto;min-height:0}:not(.is-dialog)>section{z-index:0}footer{background-color:var(--ec-background-color-body);order:3;padding:0 1.5rem;height:4.5rem;flex:none;display:flex;align-items:center}.is-dialog header{padding:0}.is-dialog .titlebar{background-color:var(--ec-background-color);padding:1rem}.is-dialog ec-banner{margin:0}.is-dialog section{padding:var(--ec-page-view-padding-section, 1rem 1rem 1.5rem)}.sticky-footer section{padding-bottom:4.5rem}.sticky-footer footer{position:sticky;bottom:0;z-index:var(--ec-z-index-sticky-page-header)}.fit-content>section{flex:1 1;display:flex}.footer-visible section{padding-bottom:0}.overlay-visible header{z-index:var(--ec-z-index-overlay)1}.overlay-visible ec-banner{display:none}:host(.bg-content) header{background-color:var(--ec-background-color)}:host(.bg-content) section{background-color:var(--ec-background-color)}:host(.bg-content) footer{background-color:var(--ec-background-color)}#pageViewDialogClose{position:absolute;top:1rem;right:1rem;z-index:calc(var(--ec-z-index-overlay) + 1)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$3.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: ViewOverlayComponent, selector: "[ecOverlay]", inputs: ["status", "message", "action", "noDataTemplate", "displayAsMask", "overlayClassList"] }, { kind: "component", type: BannerComponent, selector: "ec-banner", inputs: ["hidden", "id", "type", "bannerStyle", "title", "text", "list", "showCloseBtn", "autoHideOnClose", "customIcon", "rememberClosed"], outputs: ["closed"] }, { kind: "component", type: DropdownComponent, selector: "ec-dropdown", inputs: ["id", "autofocus", "status", "disabled", "label", "icon", "buttonType", "buttonAlignment", "buttonTitle", "tabindex", "showArrow", "items", "menuTemplateType", "menuTitle", "menuHeight", "menuWidth", "menuMinWidth", "menuPosition", "menuFooter", "popupFixed", "buttonCustomTemplate", "pending"], outputs: ["itemSelected", "popupOpened"] }, { kind: "component", type: PageTitleComponent, selector: "app-page-title", inputs: ["title", "titleIcon", "subTitle", "subTitleUrl"] }] }); }
|
11432
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PageViewComponent, selector: "ec-page-view", inputs: { isDialog: "isDialog", readonly: "readonly", status: "status", showHeader: "showHeader", errors: "errors", breadcrumbs: "breadcrumbs", title: "title", titleIcon: "titleIcon", subTitle: "subTitle", subTitleUrl: "subTitleUrl", moreActionsLabel: "moreActionsLabel", moreActions: "moreActions", secondaryActionLabel: "secondaryActionLabel", hideSecondaryAction: "hideSecondaryAction", hideCloseOnPending: "hideCloseOnPending", primaryActionLabel: "primaryActionLabel", hidePrimaryAction: "hidePrimaryAction", customTitleTemplate: "customTitleTemplate", customActionsTemplate: "customActionsTemplate", customHeaderTemplate: "customHeaderTemplate", footerTemplate: "footerTemplate", customErrorBannerTemplate: "customErrorBannerTemplate", stickyFooter: "stickyFooter", fitContent: "fitContent", disablePrimaryAction: "disablePrimaryAction", bgContent: "bgContent" }, outputs: { onPrimaryAction: "onPrimaryAction", onSecondaryAction: "onSecondaryAction" }, host: { properties: { "class.bg-content": "this.bgContent" }, classAttribute: "flex-grow" }, ngImport: i0, template: "<div ecOverlay\r\n [status]=\"status?.status\"\r\n [message]=\"status?.message\"\r\n [displayAsMask]=\"true\"\r\n class=\"flex-grow d-flex\"\r\n [ngClass]=\"{'bg-body': !bgContent, 'bg-content': bgContent}\">\r\n <div id=\"PageViewScrollContainer\"\r\n class=\"d-flex flex-column flex-grow scroll-y\"\r\n [class.is-dialog]=\"isDialog\"\r\n [class.fit-content]=\"fitContent\"\r\n [class.sticky-footer]=\"stickyFooter && !!footerTemplate\"\r\n [class.overlay-visible]=\"status?.status !== 'hasData'\"\r\n [class.footer-visible]=\"!!footerTemplate\"\r\n cdkScrollable>\r\n <section>\r\n <ng-content></ng-content>\r\n </section>\r\n\r\n <footer *ngIf=\"footerTemplate\">\r\n <ng-container *ngTemplateOutlet=\"footerTemplate\"></ng-container>\r\n </footer>\r\n\r\n <header *ngIf=\"showHeader\">\r\n <ol id=\"breadcrumbs\"\r\n *ngIf=\"breadcrumbs?.length && !isDialog\">\r\n <li *ngFor=\"let crumb of breadcrumbs; last as isLast\">\r\n <a *ngIf=\"crumb.url; else label\"\r\n [routerLink]=\"crumb.url\">\r\n <ng-container *ngTemplateOutlet=\"label\"></ng-container>\r\n </a>\r\n <ng-template #label>{{crumb.label}}</ng-template>\r\n </li>\r\n </ol>\r\n\r\n <div class=\"titlebar\">\r\n <app-page-title *ngIf=\"!customTitleTemplate; else customTitle\"\r\n [title]=\"title\"\r\n [subTitle]=\"subTitle\"\r\n [subTitleUrl]=\"subTitleUrl\"\r\n [titleIcon]=\"titleIcon\"\r\n class=\"title text-truncate\">\r\n </app-page-title>\r\n\r\n <ng-template #customTitle>\r\n <div class=\"title\">\r\n <ng-container *ngTemplateOutlet=\"customTitleTemplate\"></ng-container>\r\n </div>\r\n </ng-template>\r\n\r\n <div class=\"actions\">\r\n <ec-button id=\"primaryAction\"\r\n class=\"ml-2\"\r\n *ngIf=\"!hidePrimaryAction && onPrimaryAction.observers?.length && !readonly\"\r\n [disabled]=\"status?.status === 'pending' || disablePrimaryAction\"\r\n type=\"primary\"\r\n [label]=\"primaryActionLabel\"\r\n (clicked)=\"primaryAction($event)\">\r\n </ec-button>\r\n <ec-button id=\"secondaryAction\"\r\n class=\"ml-2\"\r\n *ngIf=\"!hideSecondaryAction && onSecondaryAction.observers?.length\"\r\n type=\"secondary\"\r\n [label]=\"readonly ? 'Close' : secondaryActionLabel\"\r\n (clicked)=\"secondaryAction($event)\">\r\n </ec-button>\r\n <ec-dropdown id=\"moreActions\"\r\n *ngIf=\"moreActions?.length && !readonly\"\r\n [disabled]=\"status?.status === 'pending'\"\r\n class=\"ml-2\"\r\n buttonType=\"text\"\r\n [label]=\"moreActionsLabel\"\r\n [items]=\"moreActions\">\r\n </ec-dropdown>\r\n <ng-container *ngTemplateOutlet=\"customActionsTemplate\"></ng-container>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"customHeaderTemplate\"\r\n class=\"page-header\">\r\n <ng-container *ngTemplateOutlet=\"customHeaderTemplate\"></ng-container>\r\n </div>\r\n\r\n <ec-banner *ngIf=\"!customErrorBannerTemplate && errors; else customErrorBannerOutlet\"\r\n id=\"pageViewErrors\"\r\n [class.border-bottom-0]=\"!isDialog\">\r\n <div [innerHtml]=\"errors\"></div>\r\n </ec-banner>\r\n\r\n <ng-template #customErrorBannerOutlet>\r\n <ec-banner *ngIf=\"errors\"\r\n id=\"pageViewErrors\"\r\n [class.border-bottom-0]=\"!isDialog\">\r\n <ng-container *ngTemplateOutlet=\"customErrorBannerTemplate\"></ng-container>\r\n </ec-banner>\r\n </ng-template>\r\n </header>\r\n </div>\r\n\r\n <ec-button *ngIf=\"isDialog && ( (status?.status === 'pending' && !hideCloseOnPending) || status?.status === 'error')\"\r\n id=\"pageViewDialogClose\"\r\n type=\"icon\"\r\n icon=\"icon-cancel\"\r\n (clicked)=\"closeDialog()\">\r\n </ec-button>\r\n</div>", styles: [":host{flex:1 1;min-height:0;display:flex}header{background-color:var(--ec-background-color-body);position:sticky;top:0;order:1;padding:1rem 1.5rem .5rem;flex:none;z-index:var(--ec-z-index-sticky-page-header)}ol{font-size:var(--ec-font-size-label);line-height:1rem;grid-column:1/3;grid-row:1/2;list-style:none;padding:0;margin:0 0 .25rem}ol li{display:inline}ol li:not(:last-child):after{content:\" / \";display:inline;color:var(--ec-color-secondary-dark)}div[ecOverlay]{position:relative}.titlebar{display:grid;grid-template-columns:auto max-content;grid-template-rows:max-content max-content;gap:0 1rem}.title{grid-column:1/2;grid-row:2/3;align-self:center}.actions{grid-column:2/3;grid-row:2/3;display:flex;flex-direction:row-reverse}ec-banner{margin-top:1rem}section{padding:var(--ec-page-view-padding-section, .5rem 1.5rem 2rem);order:2;flex:1 0 auto;min-height:0}:not(.is-dialog)>section{z-index:0}footer{background-color:var(--ec-background-color-body);order:3;padding:0 1.5rem;height:4.5rem;flex:none;display:flex;align-items:center}.is-dialog header{padding:0}.is-dialog .titlebar{background-color:var(--ec-background-color);padding:1rem}.is-dialog ec-banner{margin:0}.is-dialog section{padding:var(--ec-page-view-padding-section, 1rem 1rem 1.5rem)}.sticky-footer section{padding-bottom:4.5rem}.sticky-footer footer{position:sticky;bottom:0;z-index:var(--ec-z-index-sticky-page-header)}.fit-content>section{flex:1 1;display:flex}.footer-visible section{padding-bottom:0}.overlay-visible header{z-index:var(--ec-z-index-overlay)1}.overlay-visible ec-banner{display:none}:host(.bg-content) header{background-color:var(--ec-background-color)}:host(.bg-content) section{background-color:var(--ec-background-color)}:host(.bg-content) footer{background-color:var(--ec-background-color)}#pageViewDialogClose{position:absolute;top:1rem;right:1rem;z-index:calc(var(--ec-z-index-overlay) + 1)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1$4.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: ViewOverlayComponent, selector: "[ecOverlay]", inputs: ["status", "message", "action", "noDataTemplate", "displayAsMask", "overlayClassList"] }, { kind: "component", type: BannerComponent, selector: "ec-banner", inputs: ["hidden", "id", "type", "bannerStyle", "title", "text", "list", "showCloseBtn", "autoHideOnClose", "customIcon", "rememberClosed"], outputs: ["closed"] }, { kind: "component", type: DropdownComponent, selector: "ec-dropdown", inputs: ["id", "autofocus", "status", "disabled", "label", "icon", "buttonType", "buttonAlignment", "buttonTitle", "tabindex", "showArrow", "items", "menuTemplateType", "menuTitle", "menuHeight", "menuWidth", "menuMinWidth", "menuPosition", "menuFooter", "popupFixed", "buttonCustomTemplate", "pending"], outputs: ["itemSelected", "popupOpened"] }, { kind: "component", type: PageTitleComponent, selector: "app-page-title", inputs: ["title", "titleIcon", "subTitle", "subTitleUrl"] }] }); }
|
10278
11433
|
}
|
10279
11434
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PageViewComponent, decorators: [{
|
10280
11435
|
type: Component,
|
@@ -10794,7 +11949,8 @@ class ComponentsModule {
|
|
10794
11949
|
TooltipDirective,
|
10795
11950
|
CalendarComponent,
|
10796
11951
|
CalendarItemComponent,
|
10797
|
-
DateInputComponent
|
11952
|
+
DateInputComponent,
|
11953
|
+
KeyboardNavContainerDirective], imports: [CommonModule,
|
10798
11954
|
FormsModule,
|
10799
11955
|
ReactiveFormsModule,
|
10800
11956
|
RouterModule,
|
@@ -10864,7 +12020,8 @@ class ComponentsModule {
|
|
10864
12020
|
CopyTableButtonDirective,
|
10865
12021
|
TooltipDirective,
|
10866
12022
|
CalendarComponent,
|
10867
|
-
DateInputComponent
|
12023
|
+
DateInputComponent,
|
12024
|
+
KeyboardNavContainerDirective] }); }
|
10868
12025
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComponentsModule, providers: [
|
10869
12026
|
FormGroupHelper,
|
10870
12027
|
DialogService,
|
@@ -10957,7 +12114,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
10957
12114
|
TooltipDirective,
|
10958
12115
|
CalendarComponent,
|
10959
12116
|
CalendarItemComponent,
|
10960
|
-
DateInputComponent
|
12117
|
+
DateInputComponent,
|
12118
|
+
KeyboardNavContainerDirective
|
10961
12119
|
],
|
10962
12120
|
imports: [
|
10963
12121
|
CommonModule,
|
@@ -11043,7 +12201,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
11043
12201
|
CopyTableButtonDirective,
|
11044
12202
|
TooltipDirective,
|
11045
12203
|
CalendarComponent,
|
11046
|
-
DateInputComponent
|
12204
|
+
DateInputComponent,
|
12205
|
+
KeyboardNavContainerDirective
|
11047
12206
|
]
|
11048
12207
|
}]
|
11049
12208
|
}] });
|
@@ -11051,6 +12210,104 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
11051
12210
|
class RadioButtonOption {
|
11052
12211
|
}
|
11053
12212
|
|
12213
|
+
class CustomValidators {
|
12214
|
+
/**
|
12215
|
+
* Tests the control using Angular's required validator, except returns
|
12216
|
+
* an error map that triggers the plural 'are required' validation message
|
12217
|
+
* instead of 'is required'
|
12218
|
+
*
|
12219
|
+
* @returns An error map with the `requiredPlural` property
|
12220
|
+
* if the validation check fails, otherwise `null`.
|
12221
|
+
*/
|
12222
|
+
static { this.requiredPlural = (control) => {
|
12223
|
+
return Validators.required(control) !== null ? { requiredPlural: true } : null;
|
12224
|
+
}; }
|
12225
|
+
/**
|
12226
|
+
* Returns a validation error if the control's value is not valid JSON.
|
12227
|
+
*/
|
12228
|
+
static { this.json = (control) => {
|
12229
|
+
return (control.value && JsonHelper.tryParseJSON(control.value) === undefined) ? { json: true } : null;
|
12230
|
+
}; }
|
12231
|
+
/**
|
12232
|
+
* Returns a validation error if the control's value is not a valid domain.
|
12233
|
+
*/
|
12234
|
+
static { this.domain = (control) => {
|
12235
|
+
return (control.value && domainPattern.test(control.value) === false) ? { domain: true } : null;
|
12236
|
+
}; }
|
12237
|
+
}
|
12238
|
+
|
12239
|
+
var HierarchyMocks;
|
12240
|
+
(function (HierarchyMocks) {
|
12241
|
+
HierarchyMocks.mockRoot = () => ({
|
12242
|
+
id: "1",
|
12243
|
+
level: 0,
|
12244
|
+
hasChildren: true,
|
12245
|
+
children: [],
|
12246
|
+
label: ''
|
12247
|
+
});
|
12248
|
+
HierarchyMocks.bldgWithChildren = () => {
|
12249
|
+
return {
|
12250
|
+
placeId: 3, parentId: 0, placeTypeId: 2, placeCode: 'HASCHILDREN_BLDG', placeInfo: 'A Cool Bldg Has Children',
|
12251
|
+
hasChildren: true, placeChildren: [], meterChildren: [], hasActiveChildren: true
|
12252
|
+
};
|
12253
|
+
};
|
12254
|
+
HierarchyMocks.bldgWithChildrenHierarchyItem = () => ({
|
12255
|
+
id: HierarchyMocks.bldgWithChildren().placeId.toString(), icon: 'icon-building', label: `${HierarchyMocks.bldgWithChildren().placeInfo} [${HierarchyMocks.bldgWithChildren().placeCode}]`,
|
12256
|
+
children: [], hasChildren: true, level: 1, selectable: true, topLevel: false
|
12257
|
+
});
|
12258
|
+
HierarchyMocks.orgWithChildren = () => {
|
12259
|
+
return {
|
12260
|
+
placeId: 1, parentId: 0, placeTypeId: 1, placeCode: 'HASCHILDREN_ORG', placeInfo: 'A Org Has Children',
|
12261
|
+
hasChildren: true, placeChildren: [], meterChildren: [], hasActiveChildren: true
|
12262
|
+
};
|
12263
|
+
};
|
12264
|
+
HierarchyMocks.orgWithChildrenHierarchyItem = () => ({
|
12265
|
+
id: HierarchyMocks.orgWithChildren().placeId.toString(), icon: 'icon-organization', label: `${HierarchyMocks.orgWithChildren().placeInfo} [${HierarchyMocks.orgWithChildren().placeCode}]`,
|
12266
|
+
children: [], hasChildren: true, level: 1, selectable: true, topLevel: true
|
12267
|
+
});
|
12268
|
+
HierarchyMocks.orgWithoutChildren = () => {
|
12269
|
+
return {
|
12270
|
+
placeId: 2, parentId: 0, placeTypeId: 1, placeCode: 'NOCHILDREN_ORG', placeInfo: 'No Children Org',
|
12271
|
+
hasChildren: false, placeChildren: [], meterChildren: [], hasActiveChildren: false
|
12272
|
+
};
|
12273
|
+
};
|
12274
|
+
HierarchyMocks.orgWithoutChildrenHierarchyItem = () => ({
|
12275
|
+
id: HierarchyMocks.orgWithoutChildren().placeId.toString(), icon: 'icon-organization', label: `${HierarchyMocks.orgWithoutChildren().placeInfo} [${HierarchyMocks.orgWithoutChildren().placeCode}]`,
|
12276
|
+
children: [], hasChildren: false, level: 1, selectable: true, topLevel: true
|
12277
|
+
});
|
12278
|
+
HierarchyMocks.bldgWithoutChildren = () => {
|
12279
|
+
return {
|
12280
|
+
placeId: 4, parentId: 0, placeTypeId: 2, placeCode: 'NOCHILDREN_BLDG', placeInfo: 'Zzz No Children Bldg',
|
12281
|
+
hasChildren: false, placeChildren: [], meterChildren: [], hasActiveChildren: false
|
12282
|
+
};
|
12283
|
+
};
|
12284
|
+
HierarchyMocks.bldgWithoutChildrenHierarchyItem = () => ({
|
12285
|
+
id: HierarchyMocks.bldgWithoutChildren().placeId.toString(), icon: 'icon-building', label: `${HierarchyMocks.bldgWithoutChildren().placeInfo} [${HierarchyMocks.bldgWithoutChildren().placeCode}]`,
|
12286
|
+
children: [], hasChildren: false, level: 1, selectable: true, topLevel: false
|
12287
|
+
});
|
12288
|
+
HierarchyMocks.sortedHierarchyPlaces = () => [
|
12289
|
+
HierarchyMocks.bldgWithChildrenHierarchyItem(), HierarchyMocks.orgWithChildrenHierarchyItem(), HierarchyMocks.orgWithoutChildrenHierarchyItem(), HierarchyMocks.bldgWithoutChildrenHierarchyItem()
|
12290
|
+
];
|
12291
|
+
})(HierarchyMocks || (HierarchyMocks = {}));
|
12292
|
+
|
12293
|
+
/** Tag contains a label and type. Type is default by default */
|
12294
|
+
class Tag {
|
12295
|
+
constructor(label, type, classList, icon, isDismissable, tooltip, url, target) {
|
12296
|
+
this.target = '_self';
|
12297
|
+
this.label = label;
|
12298
|
+
this.type = type || 'info';
|
12299
|
+
this.icon = icon;
|
12300
|
+
this.isDismissable = isDismissable ?? false;
|
12301
|
+
this.tooltip = tooltip;
|
12302
|
+
this.url = url;
|
12303
|
+
this.target = target || '_self';
|
12304
|
+
if (classList) {
|
12305
|
+
this.classList = classList;
|
12306
|
+
}
|
12307
|
+
}
|
12308
|
+
}
|
12309
|
+
;
|
12310
|
+
|
11054
12311
|
/** Common unicode strings */
|
11055
12312
|
class UnicodeStrings {
|
11056
12313
|
/** Equivalent of – */
|
@@ -11108,50 +12365,6 @@ function safeToLower(item, prop) {
|
|
11108
12365
|
}
|
11109
12366
|
;
|
11110
12367
|
|
11111
|
-
/** Tag contains a label and type. Type is default by default */
|
11112
|
-
class Tag {
|
11113
|
-
constructor(label, type, classList, icon, isDismissable, tooltip, url, target) {
|
11114
|
-
this.target = '_self';
|
11115
|
-
this.label = label;
|
11116
|
-
this.type = type || 'info';
|
11117
|
-
this.icon = icon;
|
11118
|
-
this.isDismissable = isDismissable ?? false;
|
11119
|
-
this.tooltip = tooltip;
|
11120
|
-
this.url = url;
|
11121
|
-
this.target = target || '_self';
|
11122
|
-
if (classList) {
|
11123
|
-
this.classList = classList;
|
11124
|
-
}
|
11125
|
-
}
|
11126
|
-
}
|
11127
|
-
;
|
11128
|
-
|
11129
|
-
class CustomValidators {
|
11130
|
-
/**
|
11131
|
-
* Tests the control using Angular's required validator, except returns
|
11132
|
-
* an error map that triggers the plural 'are required' validation message
|
11133
|
-
* instead of 'is required'
|
11134
|
-
*
|
11135
|
-
* @returns An error map with the `requiredPlural` property
|
11136
|
-
* if the validation check fails, otherwise `null`.
|
11137
|
-
*/
|
11138
|
-
static { this.requiredPlural = (control) => {
|
11139
|
-
return Validators.required(control) !== null ? { requiredPlural: true } : null;
|
11140
|
-
}; }
|
11141
|
-
/**
|
11142
|
-
* Returns a validation error if the control's value is not valid JSON.
|
11143
|
-
*/
|
11144
|
-
static { this.json = (control) => {
|
11145
|
-
return (control.value && JsonHelper.tryParseJSON(control.value) === undefined) ? { json: true } : null;
|
11146
|
-
}; }
|
11147
|
-
/**
|
11148
|
-
* Returns a validation error if the control's value is not a valid domain.
|
11149
|
-
*/
|
11150
|
-
static { this.domain = (control) => {
|
11151
|
-
return (control.value && domainPattern.test(control.value) === false) ? { domain: true } : null;
|
11152
|
-
}; }
|
11153
|
-
}
|
11154
|
-
|
11155
12368
|
var PageStatus;
|
11156
12369
|
(function (PageStatus) {
|
11157
12370
|
PageStatus["Loading"] = "loading";
|
@@ -11548,6 +12761,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
11548
12761
|
args: ['class']
|
11549
12762
|
}] } });
|
11550
12763
|
|
12764
|
+
class CopyButtonBaseTestInjectorFactory {
|
12765
|
+
static getComponentInjector() {
|
12766
|
+
return Injector.create({
|
12767
|
+
providers: [
|
12768
|
+
{
|
12769
|
+
provide: ClipboardService,
|
12770
|
+
useFactory: () => SpyFactory.createSpy(ClipboardService),
|
12771
|
+
deps: []
|
12772
|
+
}
|
12773
|
+
]
|
12774
|
+
});
|
12775
|
+
}
|
12776
|
+
}
|
12777
|
+
|
12778
|
+
class HierarchyBaseTestInjectorFactory {
|
12779
|
+
static getComponentInjector() {
|
12780
|
+
return Injector.create({
|
12781
|
+
providers: [
|
12782
|
+
{
|
12783
|
+
provide: TelemetryService,
|
12784
|
+
useFactory: () => SpyFactory.createSpy(TelemetryService),
|
12785
|
+
deps: []
|
12786
|
+
}
|
12787
|
+
]
|
12788
|
+
});
|
12789
|
+
}
|
12790
|
+
}
|
12791
|
+
|
11551
12792
|
const clickEvent = new MouseEvent('click');
|
11552
12793
|
;
|
11553
12794
|
/**
|
@@ -11967,88 +13208,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
11967
13208
|
type: Directive
|
11968
13209
|
}], ctorParameters: () => [{ type: i0.Injector }] });
|
11969
13210
|
|
11970
|
-
var HierarchyMocks;
|
11971
|
-
(function (HierarchyMocks) {
|
11972
|
-
HierarchyMocks.mockRoot = () => ({
|
11973
|
-
id: "1",
|
11974
|
-
level: 0,
|
11975
|
-
hasChildren: true,
|
11976
|
-
children: [],
|
11977
|
-
label: ''
|
11978
|
-
});
|
11979
|
-
HierarchyMocks.bldgWithChildren = () => {
|
11980
|
-
return {
|
11981
|
-
placeId: 3, parentId: 0, placeTypeId: 2, placeCode: 'HASCHILDREN_BLDG', placeInfo: 'A Cool Bldg Has Children',
|
11982
|
-
hasChildren: true, placeChildren: [], meterChildren: [], hasActiveChildren: true
|
11983
|
-
};
|
11984
|
-
};
|
11985
|
-
HierarchyMocks.bldgWithChildrenHierarchyItem = () => ({
|
11986
|
-
id: HierarchyMocks.bldgWithChildren().placeId.toString(), icon: 'icon-building', label: `${HierarchyMocks.bldgWithChildren().placeInfo} [${HierarchyMocks.bldgWithChildren().placeCode}]`,
|
11987
|
-
children: [], hasChildren: true, level: 1, selectable: true, topLevel: false
|
11988
|
-
});
|
11989
|
-
HierarchyMocks.orgWithChildren = () => {
|
11990
|
-
return {
|
11991
|
-
placeId: 1, parentId: 0, placeTypeId: 1, placeCode: 'HASCHILDREN_ORG', placeInfo: 'A Org Has Children',
|
11992
|
-
hasChildren: true, placeChildren: [], meterChildren: [], hasActiveChildren: true
|
11993
|
-
};
|
11994
|
-
};
|
11995
|
-
HierarchyMocks.orgWithChildrenHierarchyItem = () => ({
|
11996
|
-
id: HierarchyMocks.orgWithChildren().placeId.toString(), icon: 'icon-organization', label: `${HierarchyMocks.orgWithChildren().placeInfo} [${HierarchyMocks.orgWithChildren().placeCode}]`,
|
11997
|
-
children: [], hasChildren: true, level: 1, selectable: true, topLevel: true
|
11998
|
-
});
|
11999
|
-
HierarchyMocks.orgWithoutChildren = () => {
|
12000
|
-
return {
|
12001
|
-
placeId: 2, parentId: 0, placeTypeId: 1, placeCode: 'NOCHILDREN_ORG', placeInfo: 'No Children Org',
|
12002
|
-
hasChildren: false, placeChildren: [], meterChildren: [], hasActiveChildren: false
|
12003
|
-
};
|
12004
|
-
};
|
12005
|
-
HierarchyMocks.orgWithoutChildrenHierarchyItem = () => ({
|
12006
|
-
id: HierarchyMocks.orgWithoutChildren().placeId.toString(), icon: 'icon-organization', label: `${HierarchyMocks.orgWithoutChildren().placeInfo} [${HierarchyMocks.orgWithoutChildren().placeCode}]`,
|
12007
|
-
children: [], hasChildren: false, level: 1, selectable: true, topLevel: true
|
12008
|
-
});
|
12009
|
-
HierarchyMocks.bldgWithoutChildren = () => {
|
12010
|
-
return {
|
12011
|
-
placeId: 4, parentId: 0, placeTypeId: 2, placeCode: 'NOCHILDREN_BLDG', placeInfo: 'Zzz No Children Bldg',
|
12012
|
-
hasChildren: false, placeChildren: [], meterChildren: [], hasActiveChildren: false
|
12013
|
-
};
|
12014
|
-
};
|
12015
|
-
HierarchyMocks.bldgWithoutChildrenHierarchyItem = () => ({
|
12016
|
-
id: HierarchyMocks.bldgWithoutChildren().placeId.toString(), icon: 'icon-building', label: `${HierarchyMocks.bldgWithoutChildren().placeInfo} [${HierarchyMocks.bldgWithoutChildren().placeCode}]`,
|
12017
|
-
children: [], hasChildren: false, level: 1, selectable: true, topLevel: false
|
12018
|
-
});
|
12019
|
-
HierarchyMocks.sortedHierarchyPlaces = () => [
|
12020
|
-
HierarchyMocks.bldgWithChildrenHierarchyItem(), HierarchyMocks.orgWithChildrenHierarchyItem(), HierarchyMocks.orgWithoutChildrenHierarchyItem(), HierarchyMocks.bldgWithoutChildrenHierarchyItem()
|
12021
|
-
];
|
12022
|
-
})(HierarchyMocks || (HierarchyMocks = {}));
|
12023
|
-
|
12024
|
-
class HierarchyBaseTestInjectorFactory {
|
12025
|
-
static getComponentInjector() {
|
12026
|
-
return Injector.create({
|
12027
|
-
providers: [
|
12028
|
-
{
|
12029
|
-
provide: TelemetryService,
|
12030
|
-
useFactory: () => SpyFactory.createSpy(TelemetryService),
|
12031
|
-
deps: []
|
12032
|
-
}
|
12033
|
-
]
|
12034
|
-
});
|
12035
|
-
}
|
12036
|
-
}
|
12037
|
-
|
12038
|
-
class CopyButtonBaseTestInjectorFactory {
|
12039
|
-
static getComponentInjector() {
|
12040
|
-
return Injector.create({
|
12041
|
-
providers: [
|
12042
|
-
{
|
12043
|
-
provide: ClipboardService,
|
12044
|
-
useFactory: () => SpyFactory.createSpy(ClipboardService),
|
12045
|
-
deps: []
|
12046
|
-
}
|
12047
|
-
]
|
12048
|
-
});
|
12049
|
-
}
|
12050
|
-
}
|
12051
|
-
|
12052
13211
|
/*
|
12053
13212
|
* Public API Surface of @energycap/components
|
12054
13213
|
*/
|
@@ -12057,5 +13216,5 @@ class CopyButtonBaseTestInjectorFactory {
|
|
12057
13216
|
* Generated bundle index. Do not edit.
|
12058
13217
|
*/
|
12059
13218
|
|
12060
|
-
export { AppBarComponent, AvatarComponent, BannerComponent, ButtonComponent, CacheService, CalendarComponent, CheckboxComponent, ClickAreaForDirective, CollapsibleToggleComponent, ComboboxComponent, ComponentsModule, ConfirmComponent, ConfirmDialogContext, CopyButtonBaseTestInjectorFactory, CopyButtonDirective, CopyTableButtonDirective, CustomValidators, DateDisplayPipe, DateInputComponent, DateTimeHelper, DialogCloseDuration, DialogCloseEvent, DialogCloseLatestEvent, DialogComponent, DialogEvent, DialogGroupComponent, DialogOpenDuration, DialogOpenEndEvent, DialogOpenStartEvent, DialogResult, DialogService, DropdownComponent, ErrorService, FileTypeExtensions, FileUploadComponent, FormControlBase, FormControlComponent, FormControlLabelComponent, FormGroupComponent, FormGroupHelper, HelpPopoverComponent, HierarchyBase, HierarchyBaseTestInjectorFactory, HierarchyItem, HierarchyMocks, HierarchyTreeComponent, HighlightTextPipe, IfViewportWidthDirective, ItemDisplayComponent, ItemPickerComponent, ItemPickerSelectableContext, JsonDisplayComponent, JsonHelper, LinkButtonComponent, MenuComponent, MockActivatedRoute, MockDateDisplayPipe, MockDialog, MockDialogContent, MockTranslateService, MockTranslationHelperService, NavGroup, NavItemActiveDirective, NumericboxComponent, Overlay, PageBaseComponent, PageBaseComponentTestHelper, PageBaseComponentTestInjectorFactory, PageInitResult, PageStatus, PageStatuses, PageTitleComponent, PageViewComponent, PanelCloseDuration, PanelOpenDuration, PopoverComponent, PopupContainerDirective, RadioButtonComponent, RadioButtonOption, RelativeDatePipe, ResizableBase, ResizableColumnComponent, ResizableComponent, RouterHelper, RowCountPipe, ScrollService, SearchableTableComponent, SelectComponent, SpinnerComponent, SplashComponent, SplashService, SpyFactory, TableComponent, TableLockedColumnComponent, TableMasterHeaderRowComponent, TableMasterRowComponent, TablePaginationComponent, TableSelectableRowComponent, TableSelectableRowContext, TabsComponent, Tag, TagsComponent, TelemetryService, TelemetryTrackerService, TextboxComponent, TimeDisplayPipe, ToastComponent, ToastEvent, ToastService, ToasterComponent, TooltipComponent, TooltipDirective, TooltipService, Tour, TourAnchor, TourComponent, TourEvent, TourService, TourStep, TreeComponent, UnicodeStrings, UserPreferenceService, ValidationMessageService, ViewOverlayComponent, WindowService, WizardBaseComponent, WizardButtonsComponent, WizardProgressComponent, canadianPostalCodeRegex, clickEvent, dateInputFormatRegex, domainPattern, findAllSpacesPattern, forEachFormControl, getApiError, getControlValue, getDecimalPattern, integerPattern, isApiError,
|
13219
|
+
export { AppBarComponent, AvatarComponent, BannerComponent, ButtonComponent, CacheService, CalendarComponent, CheckboxComponent, ClickAreaForDirective, CollapsibleToggleComponent, ComboboxComponent, ComponentsModule, ConfirmComponent, ConfirmDialogContext, CopyButtonBaseTestInjectorFactory, CopyButtonDirective, CopyTableButtonDirective, CustomValidators, DateDisplayPipe, DateInput, DateInputComponent, DateTimeHelper, DialogCloseDuration, DialogCloseEvent, DialogCloseLatestEvent, DialogComponent, DialogEvent, DialogGroupComponent, DialogOpenDuration, DialogOpenEndEvent, DialogOpenStartEvent, DialogResult, DialogService, DropdownComponent, ErrorService, FileTypeExtensions, FileUploadComponent, FormControlBase, FormControlComponent, FormControlLabelComponent, FormGroupComponent, FormGroupHelper, HelpPopoverComponent, HierarchyBase, HierarchyBaseTestInjectorFactory, HierarchyItem, HierarchyMocks, HierarchyTreeComponent, HighlightTextPipe, IfViewportWidthDirective, ItemDisplayComponent, ItemPickerComponent, ItemPickerSelectableContext, JsonDisplayComponent, JsonHelper, KeyboardNavContainerDirective, LinkButtonComponent, MenuComponent, MockActivatedRoute, MockDateDisplayPipe, MockDialog, MockDialogContent, MockTranslateService, MockTranslationHelperService, NavGroup, NavItemActiveDirective, NumericboxComponent, Overlay, PageBaseComponent, PageBaseComponentTestHelper, PageBaseComponentTestInjectorFactory, PageInitResult, PageStatus, PageStatuses, PageTitleComponent, PageViewComponent, PanelCloseDuration, PanelOpenDuration, PopoverComponent, PopupContainerDirective, RadioButtonComponent, RadioButtonOption, RelativeDatePipe, ResizableBase, ResizableColumnComponent, ResizableComponent, RouterHelper, RowCountPipe, ScrollService, SearchableTableComponent, SelectComponent, SpinnerComponent, SplashComponent, SplashService, SpyFactory, TableComponent, TableLockedColumnComponent, TableMasterHeaderRowComponent, TableMasterRowComponent, TablePaginationComponent, TableSelectableRowComponent, TableSelectableRowContext, TabsComponent, Tag, TagsComponent, TelemetryService, TelemetryTrackerService, TextboxComponent, TimeDisplayPipe, ToastComponent, ToastEvent, ToastService, ToasterComponent, TooltipComponent, TooltipDirective, TooltipService, Tour, TourAnchor, TourComponent, TourEvent, TourService, TourStep, TreeComponent, UnicodeStrings, UserPreferenceService, ValidationMessageService, ViewOverlayComponent, WindowService, WizardBaseComponent, WizardButtonsComponent, WizardProgressComponent, canadianPostalCodeRegex, clickEvent, dateInputFormatRegex, domainPattern, findAllSpacesPattern, forEachFormControl, getApiError, getControlValue, getDecimalPattern, integerPattern, isApiError, menuAnimationSpeed, mockRouterFactory, mockRouterHelperFactory, numericboxValidation, orderByIgnoreCase, otherZipCodeRegex, phoneNumberValidationPattern, sortByIgnoreCase, textboxValidation, unitedStatesZipCodeRegex, urlValidationPattern, validateFormGroupValuesAreUnique };
|
12061
13220
|
//# sourceMappingURL=energycap-components.mjs.map
|