novo-elements 5.7.0 → 5.11.0

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.
Files changed (46) hide show
  1. package/bundles/novo-elements.umd.js +333 -243
  2. package/bundles/novo-elements.umd.js.map +1 -1
  3. package/bundles/novo-elements.umd.min.js +1 -1
  4. package/bundles/novo-elements.umd.min.js.map +1 -1
  5. package/elements/data-table/cell-headers/data-table-checkbox-header-cell.component.d.ts +5 -1
  6. package/elements/data-table/cells/data-table-checkbox-cell.component.d.ts +3 -0
  7. package/elements/data-table/data-table-clear-button.component.d.ts +2 -0
  8. package/elements/data-table/data-table.component.d.ts +3 -1
  9. package/elements/data-table/data-table.component.scss +5 -1
  10. package/elements/data-table/interfaces.d.ts +3 -0
  11. package/elements/data-table/state/data-table-state.service.d.ts +6 -2
  12. package/elements/date-picker/DatePicker.d.ts +1 -0
  13. package/elements/date-picker/DatePickerInput.d.ts +1 -0
  14. package/elements/date-time-picker/DateTimePicker.d.ts +1 -0
  15. package/elements/date-time-picker/DateTimePickerInput.d.ts +1 -0
  16. package/elements/form/FormInterfaces.d.ts +1 -0
  17. package/elements/form/NovoFormControl.d.ts +1 -0
  18. package/elements/form/controls/BaseControl.d.ts +1 -0
  19. package/esm2015/elements/data-table/cell-headers/data-table-checkbox-header-cell.component.js +26 -6
  20. package/esm2015/elements/data-table/cells/data-table-checkbox-cell.component.js +16 -5
  21. package/esm2015/elements/data-table/data-table-clear-button.component.js +9 -1
  22. package/esm2015/elements/data-table/data-table.component.js +8 -3
  23. package/esm2015/elements/data-table/data-table.source.js +5 -2
  24. package/esm2015/elements/data-table/interfaces.js +1 -1
  25. package/esm2015/elements/data-table/pagination/data-table-pagination.component.js +4 -1
  26. package/esm2015/elements/data-table/sort-filter/sort-filter.directive.js +3 -1
  27. package/esm2015/elements/data-table/state/data-table-state.service.js +31 -7
  28. package/esm2015/elements/date-picker/DatePicker.js +3 -2
  29. package/esm2015/elements/date-picker/DatePickerInput.js +3 -1
  30. package/esm2015/elements/date-time-picker/DateTimePicker.js +3 -1
  31. package/esm2015/elements/date-time-picker/DateTimePickerInput.js +3 -1
  32. package/esm2015/elements/form/ControlTemplates.js +2 -2
  33. package/esm2015/elements/form/FormInterfaces.js +1 -1
  34. package/esm2015/elements/form/NovoFormControl.js +2 -1
  35. package/esm2015/elements/form/controls/BaseControl.js +2 -1
  36. package/esm2015/elements/form/extras/address/Address.js +5 -1
  37. package/esm2015/index.js +1 -1
  38. package/esm2015/services/novo-label-service.js +2 -1
  39. package/esm2015/utils/form-utils/FormUtils.js +18 -17
  40. package/fesm2015/novo-elements.js +322 -232
  41. package/fesm2015/novo-elements.js.map +1 -1
  42. package/index.d.ts +1 -1
  43. package/novo-elements.metadata.json +1 -1
  44. package/package.json +1 -1
  45. package/services/novo-label-service.d.ts +1 -0
  46. package/utils/form-utils/FormUtils.d.ts +3 -3
@@ -2971,6 +2971,7 @@ class NovoLabelService {
2971
2971
  this.clearAllNormalCase = 'Clear All';
2972
2972
  this.clearSort = 'Clear Sort';
2973
2973
  this.clearFilter = 'Clear Filter';
2974
+ this.clearSelected = 'Clear Selected';
2974
2975
  this.today = 'Today';
2975
2976
  this.now = 'Now';
2976
2977
  this.isRequired = 'is required';
@@ -7199,6 +7200,7 @@ class DataTableState {
7199
7200
  this.expandedRows = new Set();
7200
7201
  this.isForceRefresh = false;
7201
7202
  this.updates = new EventEmitter();
7203
+ this.retainSelected = false;
7202
7204
  }
7203
7205
  get userFiltered() {
7204
7206
  return !!(this.filter || this.sort || this.globalSearch || this.outsideFilter);
@@ -7216,9 +7218,12 @@ class DataTableState {
7216
7218
  this.filter = undefined;
7217
7219
  }
7218
7220
  this.page = 0;
7219
- this.selectedRows.clear();
7220
- this.resetSource.next();
7221
+ if (!this.retainSelected) {
7222
+ this.selectedRows.clear();
7223
+ this.resetSource.next();
7224
+ }
7221
7225
  this.onSortFilterChange();
7226
+ this.retainSelected = false;
7222
7227
  if (fireUpdate) {
7223
7228
  this.updates.emit({
7224
7229
  sort: this.sort,
@@ -7230,8 +7235,8 @@ class DataTableState {
7230
7235
  clearSort(fireUpdate = true) {
7231
7236
  this.sort = undefined;
7232
7237
  this.page = 0;
7233
- this.selectedRows.clear();
7234
- this.resetSource.next();
7238
+ this.checkRetainment('sort');
7239
+ this.reset(fireUpdate, true);
7235
7240
  this.onSortFilterChange();
7236
7241
  if (fireUpdate) {
7237
7242
  this.updates.emit({
@@ -7245,8 +7250,8 @@ class DataTableState {
7245
7250
  this.filter = undefined;
7246
7251
  this.globalSearch = undefined;
7247
7252
  this.page = 0;
7248
- this.selectedRows.clear();
7249
- this.resetSource.next();
7253
+ this.checkRetainment('filter');
7254
+ this.reset(fireUpdate, true);
7250
7255
  this.onSortFilterChange();
7251
7256
  if (fireUpdate) {
7252
7257
  this.updates.emit({
@@ -7256,6 +7261,19 @@ class DataTableState {
7256
7261
  });
7257
7262
  }
7258
7263
  }
7264
+ clearSelected(fireUpdate = true) {
7265
+ this.globalSearch = undefined;
7266
+ this.page = 0;
7267
+ this.reset(fireUpdate, true);
7268
+ this.onSelectionChange();
7269
+ if (fireUpdate) {
7270
+ this.updates.emit({
7271
+ sort: this.sort,
7272
+ filter: this.filter,
7273
+ globalSearch: this.globalSearch,
7274
+ });
7275
+ }
7276
+ }
7259
7277
  onSelectionChange() {
7260
7278
  this.selectionSource.next();
7261
7279
  }
@@ -7263,9 +7281,12 @@ class DataTableState {
7263
7281
  this.expandSource.next(targetId);
7264
7282
  }
7265
7283
  onPaginationChange(isPageSizeChange, pageSize) {
7284
+ this.checkRetainment('page');
7266
7285
  this.paginationSource.next({ isPageSizeChange, pageSize });
7267
7286
  }
7268
7287
  onSortFilterChange() {
7288
+ this.checkRetainment('sort');
7289
+ this.checkRetainment('filter');
7269
7290
  this.sortFilterSource.next({
7270
7291
  sort: this.sort,
7271
7292
  filter: this.filter,
@@ -7289,6 +7310,10 @@ class DataTableState {
7289
7310
  }
7290
7311
  }
7291
7312
  }
7313
+ checkRetainment(caller) {
7314
+ var _a;
7315
+ this.retainSelected = ((_a = this.selectionOptions) === null || _a === void 0 ? void 0 : _a.some(option => option.label === caller)) || this.retainSelected;
7316
+ }
7292
7317
  }
7293
7318
  DataTableState.decorators = [
7294
7319
  { type: Injectable }
@@ -7299,6 +7324,7 @@ class NovoDataTableClearButton {
7299
7324
  this.state = state;
7300
7325
  this.ref = ref;
7301
7326
  this.labels = labels;
7327
+ this.selectedClear = new EventEmitter();
7302
7328
  this.sortClear = new EventEmitter();
7303
7329
  this.filterClear = new EventEmitter();
7304
7330
  this.allClear = new EventEmitter();
@@ -7311,9 +7337,14 @@ class NovoDataTableClearButton {
7311
7337
  this.state.clearFilter();
7312
7338
  this.filterClear.emit(true);
7313
7339
  }
7340
+ clearSelected() {
7341
+ this.state.clearSelected();
7342
+ this.selectedClear.emit(true);
7343
+ }
7314
7344
  clearAll() {
7315
7345
  this.state.reset();
7316
7346
  this.allClear.emit(true);
7347
+ this.selectedClear.emit(true);
7317
7348
  this.sortClear.emit(true);
7318
7349
  this.filterClear.emit(true);
7319
7350
  }
@@ -7325,6 +7356,7 @@ NovoDataTableClearButton.decorators = [
7325
7356
  <novo-dropdown side="bottom-right" class="novo-data-table-clear-button" data-automation-id="novo-data-table-clear-dropdown">
7326
7357
  <button type="button" theme="primary" color="negative" icon="collapse" data-automation-id="novo-data-table-clear-dropdown-btn">{{ labels.clear }}</button>
7327
7358
  <list>
7359
+ <item *ngIf="state.selected.length > 0" (click)="clearSelected()" data-automation-id="novo-data-table-clear-dropdown-clear-selected">{{ labels.clearSelected }}</item>
7328
7360
  <item *ngIf="state.sort" (click)="clearSort()" data-automation-id="novo-data-table-clear-dropdown-clear-sort">{{ labels.clearSort }}</item>
7329
7361
  <item *ngIf="state.filter" (click)="clearFilter()" data-automation-id="novo-data-table-clear-dropdown-clear-filter">{{ labels.clearFilter }}</item>
7330
7362
  <item *ngIf="state.sort && state.filter" (click)="clearAll()" data-automation-id="novo-data-table-clear-dropdown-clear-all">{{ labels.clearAllNormalCase }}</item>
@@ -7340,6 +7372,7 @@ NovoDataTableClearButton.ctorParameters = () => [
7340
7372
  { type: NovoLabelService }
7341
7373
  ];
7342
7374
  NovoDataTableClearButton.propDecorators = {
7375
+ selectedClear: [{ type: Output }],
7343
7376
  sortClear: [{ type: Output }],
7344
7377
  filterClear: [{ type: Output }],
7345
7378
  allClear: [{ type: Output }]
@@ -7383,7 +7416,10 @@ class DataTableSource extends DataSource {
7383
7416
  this.current = data.results.length;
7384
7417
  this.data = data.results;
7385
7418
  // Clear selection
7386
- this.state.selectedRows.clear();
7419
+ if (!this.state.retainSelected) {
7420
+ this.state.selectedRows.clear();
7421
+ }
7422
+ this.state.retainSelected = false;
7387
7423
  this.state.onSelectionChange();
7388
7424
  // Mark changes
7389
7425
  setTimeout(() => {
@@ -7746,6 +7782,7 @@ class NovoDataTableSortFilter {
7746
7782
  }
7747
7783
  }
7748
7784
  this.state.filter = filter;
7785
+ this.state.checkRetainment('filter');
7749
7786
  this.state.reset(false, true);
7750
7787
  this.state.updates.next({ filter, sort: this.state.sort });
7751
7788
  this.state.onSortFilterChange();
@@ -7753,6 +7790,7 @@ class NovoDataTableSortFilter {
7753
7790
  sort(id, value, transform) {
7754
7791
  const sort = { id, value, transform };
7755
7792
  this.state.sort = sort;
7793
+ this.state.checkRetainment('sort');
7756
7794
  this.state.reset(false, true);
7757
7795
  this.state.updates.next({ sort, filter: this.state.filter });
7758
7796
  this.state.onSortFilterChange();
@@ -8288,6 +8326,7 @@ class NovoDataTable {
8288
8326
  this.trackByFn = (index, item) => item.id;
8289
8327
  this.templates = {};
8290
8328
  this.fixedHeader = false;
8329
+ this.maxSelected = undefined;
8291
8330
  this._hideGlobalSearch = true;
8292
8331
  this.preferencesChanged = new EventEmitter();
8293
8332
  this.loading = true;
@@ -8459,6 +8498,7 @@ class NovoDataTable {
8459
8498
  }
8460
8499
  }
8461
8500
  ngAfterContentInit() {
8501
+ var _a;
8462
8502
  if (this.displayedColumns && this.displayedColumns.length) {
8463
8503
  this.expandable = this.displayedColumns.includes('expand');
8464
8504
  }
@@ -8488,6 +8528,7 @@ class NovoDataTable {
8488
8528
  }
8489
8529
  this.state.page = this.paginationOptions ? this.paginationOptions.page : undefined;
8490
8530
  this.state.pageSize = this.paginationOptions ? this.paginationOptions.pageSize : undefined;
8531
+ this.state.selectionOptions = (_a = this.selectionOptions) !== null && _a !== void 0 ? _a : undefined;
8491
8532
  // Scrolling inside table
8492
8533
  this.novoDataTableContainer.nativeElement.addEventListener('scroll', this.scrollListenerHandler);
8493
8534
  this.initialized = true;
@@ -8732,8 +8773,8 @@ NovoDataTable.decorators = [
8732
8773
  [hidden]="dataSource?.totallyEmpty && !state.userFiltered"
8733
8774
  >
8734
8775
  <ng-container cdkColumnDef="selection">
8735
- <novo-data-table-checkbox-header-cell *cdkHeaderCellDef></novo-data-table-checkbox-header-cell>
8736
- <novo-data-table-checkbox-cell *cdkCellDef="let row; let i = index" [row]="row"></novo-data-table-checkbox-cell>
8776
+ <novo-data-table-checkbox-header-cell *cdkHeaderCellDef [maxSelected]="maxSelected"></novo-data-table-checkbox-header-cell>
8777
+ <novo-data-table-checkbox-cell *cdkCellDef="let row; let i = index" [row]="row" [maxSelected]="maxSelected"></novo-data-table-checkbox-cell>
8737
8778
  </ng-container>
8738
8779
  <ng-container cdkColumnDef="expand">
8739
8780
  <novo-data-table-expand-header-cell *cdkHeaderCellDef></novo-data-table-expand-header-cell>
@@ -8904,6 +8945,7 @@ NovoDataTable.propDecorators = {
8904
8945
  displayedColumns: [{ type: Input }],
8905
8946
  paginationOptions: [{ type: Input }],
8906
8947
  searchOptions: [{ type: Input }],
8948
+ selectionOptions: [{ type: Input }],
8907
8949
  defaultSort: [{ type: Input }],
8908
8950
  name: [{ type: Input }],
8909
8951
  allowMultipleFilters: [{ type: Input }],
@@ -8913,6 +8955,7 @@ NovoDataTable.propDecorators = {
8913
8955
  templates: [{ type: Input }],
8914
8956
  fixedHeader: [{ type: Input }],
8915
8957
  paginatorDataFeatureId: [{ type: Input }],
8958
+ maxSelected: [{ type: Input }],
8916
8959
  dataTableService: [{ type: Input }],
8917
8960
  rows: [{ type: Input }],
8918
8961
  outsideFilter: [{ type: Input }],
@@ -27403,6 +27446,7 @@ NovoAddressElement.decorators = [
27403
27446
  (focus)="isFocused($event, 'address1')"
27404
27447
  (blur)="isBlurred($event, 'address1')"
27405
27448
  (input)="onInput($event, 'address1')"
27449
+ [disabled]="disabled.address1"
27406
27450
  />
27407
27451
  </span>
27408
27452
  <span
@@ -27431,6 +27475,7 @@ NovoAddressElement.decorators = [
27431
27475
  (focus)="isFocused($event, 'address2')"
27432
27476
  (blur)="isBlurred($event, 'address2')"
27433
27477
  (input)="onInput($event, 'address2')"
27478
+ [disabled]="disabled.address2"
27434
27479
  />
27435
27480
  </span>
27436
27481
  <span
@@ -27454,6 +27499,7 @@ NovoAddressElement.decorators = [
27454
27499
  (focus)="isFocused($event, 'city')"
27455
27500
  (blur)="isBlurred($event, 'city')"
27456
27501
  (input)="onInput($event, 'city')"
27502
+ [disabled]="disabled.city"
27457
27503
  />
27458
27504
  </span>
27459
27505
  <span
@@ -27495,6 +27541,7 @@ NovoAddressElement.decorators = [
27495
27541
  (focus)="isFocused($event, 'zip')"
27496
27542
  (blur)="isBlurred($event, 'zip')"
27497
27543
  (input)="onInput($event, 'zip')"
27544
+ [disabled]="disabled.zip"
27498
27545
  />
27499
27546
  </span>
27500
27547
  <span
@@ -28894,7 +28941,7 @@ NovoDatePickerElement.decorators = [
28894
28941
  endfill: isEndFill(range, day.date, selected, selected2),
28895
28942
  'selecting-range': isSelectingRange(range, day.date, selected, selected2, hoverDay, rangeSelectMode, weekRangeSelect)
28896
28943
  }" (mouseover)="rangeHover($event, day)" [attr.data-automation-id]="day.number">
28897
- <button class="day" [attr.data-automation-id]="day.number" [disabled]="isDisabled(day.date, start, end)" (click)="select($event, day, true)">{{day.number}}</button>
28944
+ <button [title]="isDisabled(day.date, start, end) ? disabledDateMessage : ''" class="day" [attr.data-automation-id]="day.number" [disabled]="isDisabled(day.date, start, end)" (click)="select($event, day, true)">{{day.number}}</button>
28898
28945
  </td>
28899
28946
  </tr>
28900
28947
  </tbody>
@@ -28929,6 +28976,7 @@ NovoDatePickerElement.propDecorators = {
28929
28976
  range: [{ type: Input }],
28930
28977
  weekRangeSelect: [{ type: Input }],
28931
28978
  weekStart: [{ type: Input }],
28979
+ disabledDateMessage: [{ type: Input }],
28932
28980
  onSelect: [{ type: Output }]
28933
28981
  };
28934
28982
 
@@ -29334,6 +29382,7 @@ NovoDatePickerInputElement.decorators = [
29334
29382
  [end]="end"
29335
29383
  inline="true"
29336
29384
  (onSelect)="setValueAndClose($event)"
29385
+ [disabledDateMessage]="disabledDateMessage"
29337
29386
  [ngModel]="value"
29338
29387
  [weekStart]="weekStart"
29339
29388
  ></novo-date-picker>
@@ -29356,6 +29405,7 @@ NovoDatePickerInputElement.propDecorators = {
29356
29405
  format: [{ type: Input }],
29357
29406
  textMaskEnabled: [{ type: Input }],
29358
29407
  allowInvalidDate: [{ type: Input }],
29408
+ disabledDateMessage: [{ type: Input }],
29359
29409
  disabled: [{ type: HostBinding, args: ['class.disabled',] }, { type: Input }],
29360
29410
  weekStart: [{ type: Input }],
29361
29411
  blurEvent: [{ type: Output }],
@@ -29442,6 +29492,7 @@ class NovoDataTableCheckboxCell extends CdkCell {
29442
29492
  this.dataTable = dataTable;
29443
29493
  this.ref = ref;
29444
29494
  this.role = 'gridcell';
29495
+ this.maxSelected = undefined;
29445
29496
  this.checked = false;
29446
29497
  renderer.setAttribute(elementRef.nativeElement, 'data-automation-id', `novo-checkbox-column-${columnDef.cssClassFriendlyName}`);
29447
29498
  renderer.addClass(elementRef.nativeElement, `novo-checkbox-column-${columnDef.cssClassFriendlyName}`);
@@ -29455,11 +29506,19 @@ class NovoDataTableCheckboxCell extends CdkCell {
29455
29506
  this.ref.markForCheck();
29456
29507
  });
29457
29508
  }
29509
+ get isAtLimit() {
29510
+ return this.maxSelected && this.dataTable.state.selectedRows.size >= this.maxSelected && !this.checked;
29511
+ }
29458
29512
  ngOnInit() {
29459
29513
  this.checked = this.dataTable.isSelected(this.row);
29460
29514
  }
29461
29515
  onClick() {
29462
- this.dataTable.selectRow(this.row);
29516
+ if (!this.isAtLimit) {
29517
+ this.dataTable.selectRow(this.row);
29518
+ }
29519
+ }
29520
+ getTooltip() {
29521
+ return (this.isAtLimit) ? 'More than ' + this.maxSelected + ' items are not able to be selected at one time' : '';
29463
29522
  }
29464
29523
  ngOnDestroy() {
29465
29524
  if (this.selectionSubscription) {
@@ -29474,10 +29533,11 @@ NovoDataTableCheckboxCell.decorators = [
29474
29533
  { type: Component, args: [{
29475
29534
  selector: 'novo-data-table-checkbox-cell',
29476
29535
  template: `
29477
- <div class="data-table-checkbox" (click)="onClick()">
29536
+ <div class="data-table-checkbox" (click)="onClick()" [tooltip]="getTooltip()" tooltipPosition="right">
29478
29537
  <input type="checkbox" [checked]="checked">
29479
29538
  <label>
29480
- <i [class.bhi-checkbox-empty]="!checked"
29539
+ <i [class.bhi-checkbox-disabled]="isAtLimit"
29540
+ [class.bhi-checkbox-empty]="!checked"
29481
29541
  [class.bhi-checkbox-filled]="checked"></i>
29482
29542
  </label>
29483
29543
  </div>
@@ -29494,7 +29554,8 @@ NovoDataTableCheckboxCell.ctorParameters = () => [
29494
29554
  ];
29495
29555
  NovoDataTableCheckboxCell.propDecorators = {
29496
29556
  role: [{ type: HostBinding, args: ['attr.role',] }],
29497
- row: [{ type: Input }]
29557
+ row: [{ type: Input }],
29558
+ maxSelected: [{ type: Input }]
29498
29559
  };
29499
29560
 
29500
29561
  class NovoDataTableExpandCell extends CdkCell {
@@ -29632,12 +29693,211 @@ NovoDataTableExpandHeaderCell.propDecorators = {
29632
29693
  role: [{ type: HostBinding, args: ['attr.role',] }]
29633
29694
  };
29634
29695
 
29696
+ // NG2
29697
+ class NovoToastElement {
29698
+ constructor(sanitizer) {
29699
+ this.sanitizer = sanitizer;
29700
+ this.theme = 'danger';
29701
+ this.icon = 'caution';
29702
+ this.hasDialogue = false;
29703
+ this.isCloseable = false;
29704
+ this.closed = new EventEmitter();
29705
+ this.show = false;
29706
+ this.animate = false;
29707
+ this.parent = null;
29708
+ this.launched = false;
29709
+ }
29710
+ set message(m) {
29711
+ this._message = this.sanitizer.bypassSecurityTrustHtml(m);
29712
+ }
29713
+ ngOnInit() {
29714
+ if (!this.launched) {
29715
+ // clear position and time
29716
+ this.position = null;
29717
+ this.time = null;
29718
+ // set icon and styling
29719
+ this.iconClass = `bhi-${this.icon}`;
29720
+ this.alertTheme = `${this.theme} toast-container embedded`;
29721
+ if (this.hasDialogue) {
29722
+ this.alertTheme += ' dialogue';
29723
+ }
29724
+ }
29725
+ }
29726
+ ngOnChanges(changes) {
29727
+ // set icon and styling
29728
+ this.iconClass = `bhi-${this.icon}`;
29729
+ this.alertTheme = `${this.theme} toast-container embedded`;
29730
+ if (this.hasDialogue) {
29731
+ this.alertTheme += ' dialogue';
29732
+ }
29733
+ }
29734
+ clickHandler(event) {
29735
+ if (!this.isCloseable) {
29736
+ if (event) {
29737
+ event.stopPropagation();
29738
+ event.preventDefault();
29739
+ }
29740
+ if (this.parent) {
29741
+ this.parent.hide(this);
29742
+ }
29743
+ else {
29744
+ this.closed.emit({ closed: true });
29745
+ }
29746
+ }
29747
+ }
29748
+ close(event) {
29749
+ if (event) {
29750
+ event.stopPropagation();
29751
+ event.preventDefault();
29752
+ }
29753
+ if (this.parent) {
29754
+ this.parent.hide(this);
29755
+ }
29756
+ else {
29757
+ this.closed.emit({ closed: true });
29758
+ }
29759
+ }
29760
+ }
29761
+ NovoToastElement.decorators = [
29762
+ { type: Component, args: [{
29763
+ selector: 'novo-toast',
29764
+ host: {
29765
+ '[class]': 'alertTheme',
29766
+ '[class.show]': 'show',
29767
+ '[class.animate]': 'animate',
29768
+ '[class.embedded]': 'embedded',
29769
+ '(click)': '!isCloseable && clickHandler($event)',
29770
+ },
29771
+ template: `
29772
+ <div class="toast-icon">
29773
+ <i [ngClass]="iconClass"></i>
29774
+ </div>
29775
+ <div class="toast-content">
29776
+ <h5 *ngIf="title">{{title}}</h5>
29777
+ <p *ngIf="_message" [class.message-only]="!title" [innerHtml]="_message"></p>
29778
+ <div *ngIf="link" class="link-generated">
29779
+ <input type="text" [value]="link" onfocus="this.select();"/>
29780
+ </div>
29781
+ <div class="dialogue">
29782
+ <ng-content></ng-content>
29783
+ </div>
29784
+ </div>
29785
+ <div class="close-icon" *ngIf="isCloseable" (click)="close($event)">
29786
+ <i class="bhi-times"></i>
29787
+ </div>
29788
+ `
29789
+ },] }
29790
+ ];
29791
+ NovoToastElement.ctorParameters = () => [
29792
+ { type: DomSanitizer }
29793
+ ];
29794
+ NovoToastElement.propDecorators = {
29795
+ theme: [{ type: Input }],
29796
+ icon: [{ type: Input }],
29797
+ title: [{ type: Input }],
29798
+ hasDialogue: [{ type: Input }],
29799
+ link: [{ type: Input }],
29800
+ isCloseable: [{ type: Input }],
29801
+ message: [{ type: Input }],
29802
+ closed: [{ type: Output }]
29803
+ };
29804
+
29805
+ // NG2
29806
+ class NovoToastService {
29807
+ constructor(componentUtils) {
29808
+ this.componentUtils = componentUtils;
29809
+ this.references = [];
29810
+ this.icons = { default: 'bell', success: 'check', info: 'info', warning: 'warning', danger: 'remove' };
29811
+ this.defaults = { hideDelay: 3500, position: 'growlTopRight', theme: 'default' };
29812
+ }
29813
+ set parentViewContainer(view) {
29814
+ this._parentViewContainer = view;
29815
+ }
29816
+ alert(options, toastElement = NovoToastElement) {
29817
+ return new Promise((resolve) => {
29818
+ if (!this._parentViewContainer) {
29819
+ console.error('No parent view container specified for the ToastService. Set it inside your main application. \nthis.toastService.parentViewContainer = view (ViewContainerRef)');
29820
+ return;
29821
+ }
29822
+ const toast = this.componentUtils.append(toastElement, this._parentViewContainer);
29823
+ this.references.push(toast);
29824
+ this.handleAlert(toast.instance, options);
29825
+ resolve(toast);
29826
+ });
29827
+ }
29828
+ isVisible(toast) {
29829
+ return toast.show;
29830
+ }
29831
+ hide(toast) {
29832
+ toast.animate = false;
29833
+ setTimeout(() => {
29834
+ toast.show = false;
29835
+ const REF = this.references.filter((x) => x.instance === toast)[0];
29836
+ if (REF) {
29837
+ this.references.splice(this.references.indexOf(REF), 1);
29838
+ REF.destroy();
29839
+ }
29840
+ }, 300);
29841
+ }
29842
+ handleAlert(toast, options) {
29843
+ this.setToastOnSession(toast, options);
29844
+ setTimeout(() => {
29845
+ this.show(toast);
29846
+ }, 20);
29847
+ if (!toast.isCloseable) {
29848
+ this.toastTimer(toast);
29849
+ }
29850
+ }
29851
+ setToastOnSession(toast, opts) {
29852
+ const OPTIONS = typeof opts === 'object' ? opts : {};
29853
+ toast.parent = this;
29854
+ toast.title = OPTIONS.title || '';
29855
+ toast.message = OPTIONS.message || '';
29856
+ toast.hideDelay = OPTIONS.hideDelay || this.defaults.hideDelay;
29857
+ toast.link = OPTIONS.link || '';
29858
+ toast.isCloseable = OPTIONS.isCloseable || false;
29859
+ const CUSTOM_CLASS = OPTIONS.customClass || '';
29860
+ const ALERT_STYLE = OPTIONS.theme || this.defaults.theme;
29861
+ const ALERT_POSITION = OPTIONS.position || this.defaults.position;
29862
+ const ALERT_ICON = OPTIONS.icon || this.icons.default;
29863
+ toast.iconClass = `bhi-${ALERT_ICON}`;
29864
+ toast.launched = true;
29865
+ toast.alertTheme = `${ALERT_STYLE} ${ALERT_POSITION} ${CUSTOM_CLASS} toast-container launched`;
29866
+ }
29867
+ show(toast) {
29868
+ toast.show = true;
29869
+ setTimeout(addClass, 25);
29870
+ /**
29871
+ * Adds animate class to be called after a timeout
29872
+ **/
29873
+ function addClass() {
29874
+ toast.animate = true;
29875
+ }
29876
+ }
29877
+ toastTimer(toast) {
29878
+ if (toast.hideDelay < 0) {
29879
+ return;
29880
+ }
29881
+ setTimeout(() => {
29882
+ this.hide(toast);
29883
+ }, toast.hideDelay);
29884
+ }
29885
+ }
29886
+ NovoToastService.decorators = [
29887
+ { type: Injectable }
29888
+ ];
29889
+ NovoToastService.ctorParameters = () => [
29890
+ { type: ComponentUtils }
29891
+ ];
29892
+
29635
29893
  class NovoDataTableCheckboxHeaderCell extends CdkHeaderCell {
29636
- constructor(columnDef, elementRef, renderer, dataTable, ref) {
29894
+ constructor(columnDef, elementRef, renderer, dataTable, ref, toaster) {
29637
29895
  super(columnDef, elementRef);
29638
29896
  this.dataTable = dataTable;
29639
29897
  this.ref = ref;
29898
+ this.toaster = toaster;
29640
29899
  this.role = 'columnheader';
29900
+ this.maxSelected = undefined;
29641
29901
  this.checked = false;
29642
29902
  renderer.setAttribute(elementRef.nativeElement, 'data-automation-id', `novo-checkbox-column-header-${columnDef.cssClassFriendlyName}`);
29643
29903
  renderer.addClass(elementRef.nativeElement, `novo-checkbox-column-${columnDef.cssClassFriendlyName}`);
@@ -29650,6 +29910,8 @@ class NovoDataTableCheckboxHeaderCell extends CdkHeaderCell {
29650
29910
  if (event.isPageSizeChange) {
29651
29911
  this.checked = false;
29652
29912
  this.dataTable.selectRows(false);
29913
+ this.dataTable.state.checkRetainment('pageSize');
29914
+ this.dataTable.state.reset(false, true);
29653
29915
  }
29654
29916
  else {
29655
29917
  this.checked = this.dataTable.allCurrentRowsSelected();
@@ -29661,6 +29923,9 @@ class NovoDataTableCheckboxHeaderCell extends CdkHeaderCell {
29661
29923
  this.ref.markForCheck();
29662
29924
  });
29663
29925
  }
29926
+ get isAtLimit() {
29927
+ return this.maxSelected && this.dataTable.state.selectedRows.size + this.dataTable.dataSource.data.length > this.maxSelected && !this.checked;
29928
+ }
29664
29929
  ngOnDestroy() {
29665
29930
  if (this.selectionSubscription) {
29666
29931
  this.selectionSubscription.unsubscribe();
@@ -29673,7 +29938,17 @@ class NovoDataTableCheckboxHeaderCell extends CdkHeaderCell {
29673
29938
  }
29674
29939
  }
29675
29940
  onClick() {
29676
- this.dataTable.selectRows(!this.checked);
29941
+ if (this.isAtLimit) {
29942
+ this.toaster.alert({
29943
+ theme: 'danger',
29944
+ position: 'fixedTop',
29945
+ message: 'Error, more than 500 items are not able to be selected at one time',
29946
+ icon: 'caution',
29947
+ });
29948
+ }
29949
+ else {
29950
+ this.dataTable.selectRows(!this.checked);
29951
+ }
29677
29952
  }
29678
29953
  }
29679
29954
  NovoDataTableCheckboxHeaderCell.decorators = [
@@ -29696,10 +29971,12 @@ NovoDataTableCheckboxHeaderCell.ctorParameters = () => [
29696
29971
  { type: ElementRef },
29697
29972
  { type: Renderer2 },
29698
29973
  { type: NovoDataTable },
29699
- { type: ChangeDetectorRef }
29974
+ { type: ChangeDetectorRef },
29975
+ { type: NovoToastService }
29700
29976
  ];
29701
29977
  NovoDataTableCheckboxHeaderCell.propDecorators = {
29702
- role: [{ type: HostBinding, args: ['attr.role',] }]
29978
+ role: [{ type: HostBinding, args: ['attr.role',] }],
29979
+ maxSelected: [{ type: Input }]
29703
29980
  };
29704
29981
 
29705
29982
  class NovoDataTableHeaderCell extends CdkHeaderCell {
@@ -29795,10 +30072,12 @@ class NovoDataTablePagination {
29795
30072
  this.resetSubscription.unsubscribe();
29796
30073
  }
29797
30074
  selectPage(page) {
30075
+ this.state.checkRetainment('page');
29798
30076
  this.page = page;
29799
30077
  this.emitPageEvent();
29800
30078
  }
29801
30079
  nextPage() {
30080
+ this.state.checkRetainment('page');
29802
30081
  if (!this.hasNextPage()) {
29803
30082
  return;
29804
30083
  }
@@ -29807,6 +30086,7 @@ class NovoDataTablePagination {
29807
30086
  this.emitPageEvent();
29808
30087
  }
29809
30088
  previousPage() {
30089
+ this.state.checkRetainment('page');
29810
30090
  if (!this.hasPreviousPage()) {
29811
30091
  return;
29812
30092
  }
@@ -30403,6 +30683,7 @@ NovoDateTimePickerElement.decorators = [
30403
30683
  [maxYear]="maxYear"
30404
30684
  [start]="start"
30405
30685
  [end]="end"
30686
+ [disabledDateMessage]="disabledDateMessage"
30406
30687
  [weekStart]="weekStart"
30407
30688
  ></novo-date-picker>
30408
30689
  </div>
@@ -30425,6 +30706,7 @@ NovoDateTimePickerElement.propDecorators = {
30425
30706
  end: [{ type: Input }],
30426
30707
  military: [{ type: Input }],
30427
30708
  weekStart: [{ type: Input }],
30709
+ disabledDateMessage: [{ type: Input }],
30428
30710
  onSelect: [{ type: Output }]
30429
30711
  };
30430
30712
 
@@ -30536,6 +30818,7 @@ NovoDateTimePickerInputElement.decorators = [
30536
30818
  (ngModelChange)="updateDate($event)"
30537
30819
  [start]="start"
30538
30820
  [end]="end"
30821
+ [disabledDateMessage]="disabledDateMessage"
30539
30822
  [maskOptions]="maskOptions"
30540
30823
  (blurEvent)="handleBlur($event)"
30541
30824
  (focusEvent)="handleFocus($event)"
@@ -30568,6 +30851,7 @@ NovoDateTimePickerInputElement.propDecorators = {
30568
30851
  disabled: [{ type: Input }],
30569
30852
  format: [{ type: Input }],
30570
30853
  weekStart: [{ type: Input }],
30854
+ disabledDateMessage: [{ type: Input }],
30571
30855
  blurEvent: [{ type: Output }],
30572
30856
  focusEvent: [{ type: Output }],
30573
30857
  changeEvent: [{ type: Output }]
@@ -31460,6 +31744,7 @@ class BaseControl extends ControlConfig {
31460
31744
  this.isEmpty = config.isEmpty;
31461
31745
  }
31462
31746
  this.weekStart = config.weekStart || 0;
31747
+ this.disabledDateMessage = config.disabledDateMessage;
31463
31748
  }
31464
31749
  }
31465
31750
 
@@ -31906,6 +32191,7 @@ class NovoFormControl extends FormControl {
31906
32191
  this.tipWell = control.tipWell;
31907
32192
  this.customControlConfig = control.customControlConfig;
31908
32193
  this.warning = control.warning;
32194
+ this.disabledDateMessage = control.disabledDateMessage;
31909
32195
  // Reactive Form, need to enable/disable, can't bind to [disabled]
31910
32196
  if (this.readOnly) {
31911
32197
  this.disable();
@@ -32281,7 +32567,7 @@ class FormUtils {
32281
32567
  closeOnSelect: field.closeOnSelect,
32282
32568
  layoutOptions: field.layoutOptions,
32283
32569
  };
32284
- this.inferStartDate(controlConfig, field);
32570
+ this.inferDateRange(controlConfig, field);
32285
32571
  // TODO: getControlOptions should always return the correct format
32286
32572
  const optionsConfig = this.getControlOptions(field, http, config, fieldData);
32287
32573
  if (Array.isArray(optionsConfig) && !(type === 'chips' || type === 'picker')) {
@@ -32586,6 +32872,7 @@ class FormUtils {
32586
32872
  })
32587
32873
  : [];
32588
32874
  let fields = meta.fields.map((field) => {
32875
+ field.parentEntity = meta.entity;
32589
32876
  if (!field.hasOwnProperty('sortOrder')) {
32590
32877
  field.sortOrder = Number.MAX_SAFE_INTEGER - 1;
32591
32878
  }
@@ -32791,23 +33078,23 @@ class FormUtils {
32791
33078
  return addDays(startOfToday(), dateRange.minOffset);
32792
33079
  }
32793
33080
  }
32794
- /**
32795
- * Get the min start date of a Date base on field data.
32796
- */
32797
- getStartDate(field) {
32798
- if (field.allowedDateRange) {
32799
- return this.getStartDateFromRange(field.allowedDateRange);
33081
+ getEndDateFromRange(dateRange) {
33082
+ if (dateRange.maxDate) {
33083
+ return parse(dateRange.maxDate);
33084
+ }
33085
+ else if (dateRange.minOffset) {
33086
+ return addDays(startOfToday(), dateRange.minOffset);
32800
33087
  }
32801
- // there is no restriction on the start date
32802
- return null;
32803
33088
  }
32804
- inferStartDate(controlConfig, field) {
32805
- if (field.dataType === 'Date') {
32806
- const startDate = this.getStartDate(field);
32807
- if (startDate) {
32808
- controlConfig.startDate = startDate;
32809
- }
32810
- return startDate;
33089
+ /**
33090
+ * Get the min start date and max end date of a Date base on field data.
33091
+ */
33092
+ inferDateRange(controlConfig, field) {
33093
+ var _a;
33094
+ if (field.dataType === 'Date' && field.allowedDateRange) {
33095
+ controlConfig.startDate = this.getStartDateFromRange(field.allowedDateRange);
33096
+ controlConfig.endDate = this.getEndDateFromRange(field.allowedDateRange);
33097
+ controlConfig.disabledDateMessage = (_a = field.allowedDateRange) === null || _a === void 0 ? void 0 : _a.disabledDateMessage;
32811
33098
  }
32812
33099
  }
32813
33100
  inflateEmbeddedProperties(data) {
@@ -33009,203 +33296,6 @@ NovoModalService.ctorParameters = () => [
33009
33296
  { type: ComponentUtils }
33010
33297
  ];
33011
33298
 
33012
- // NG2
33013
- class NovoToastElement {
33014
- constructor(sanitizer) {
33015
- this.sanitizer = sanitizer;
33016
- this.theme = 'danger';
33017
- this.icon = 'caution';
33018
- this.hasDialogue = false;
33019
- this.isCloseable = false;
33020
- this.closed = new EventEmitter();
33021
- this.show = false;
33022
- this.animate = false;
33023
- this.parent = null;
33024
- this.launched = false;
33025
- }
33026
- set message(m) {
33027
- this._message = this.sanitizer.bypassSecurityTrustHtml(m);
33028
- }
33029
- ngOnInit() {
33030
- if (!this.launched) {
33031
- // clear position and time
33032
- this.position = null;
33033
- this.time = null;
33034
- // set icon and styling
33035
- this.iconClass = `bhi-${this.icon}`;
33036
- this.alertTheme = `${this.theme} toast-container embedded`;
33037
- if (this.hasDialogue) {
33038
- this.alertTheme += ' dialogue';
33039
- }
33040
- }
33041
- }
33042
- ngOnChanges(changes) {
33043
- // set icon and styling
33044
- this.iconClass = `bhi-${this.icon}`;
33045
- this.alertTheme = `${this.theme} toast-container embedded`;
33046
- if (this.hasDialogue) {
33047
- this.alertTheme += ' dialogue';
33048
- }
33049
- }
33050
- clickHandler(event) {
33051
- if (!this.isCloseable) {
33052
- if (event) {
33053
- event.stopPropagation();
33054
- event.preventDefault();
33055
- }
33056
- if (this.parent) {
33057
- this.parent.hide(this);
33058
- }
33059
- else {
33060
- this.closed.emit({ closed: true });
33061
- }
33062
- }
33063
- }
33064
- close(event) {
33065
- if (event) {
33066
- event.stopPropagation();
33067
- event.preventDefault();
33068
- }
33069
- if (this.parent) {
33070
- this.parent.hide(this);
33071
- }
33072
- else {
33073
- this.closed.emit({ closed: true });
33074
- }
33075
- }
33076
- }
33077
- NovoToastElement.decorators = [
33078
- { type: Component, args: [{
33079
- selector: 'novo-toast',
33080
- host: {
33081
- '[class]': 'alertTheme',
33082
- '[class.show]': 'show',
33083
- '[class.animate]': 'animate',
33084
- '[class.embedded]': 'embedded',
33085
- '(click)': '!isCloseable && clickHandler($event)',
33086
- },
33087
- template: `
33088
- <div class="toast-icon">
33089
- <i [ngClass]="iconClass"></i>
33090
- </div>
33091
- <div class="toast-content">
33092
- <h5 *ngIf="title">{{title}}</h5>
33093
- <p *ngIf="_message" [class.message-only]="!title" [innerHtml]="_message"></p>
33094
- <div *ngIf="link" class="link-generated">
33095
- <input type="text" [value]="link" onfocus="this.select();"/>
33096
- </div>
33097
- <div class="dialogue">
33098
- <ng-content></ng-content>
33099
- </div>
33100
- </div>
33101
- <div class="close-icon" *ngIf="isCloseable" (click)="close($event)">
33102
- <i class="bhi-times"></i>
33103
- </div>
33104
- `
33105
- },] }
33106
- ];
33107
- NovoToastElement.ctorParameters = () => [
33108
- { type: DomSanitizer }
33109
- ];
33110
- NovoToastElement.propDecorators = {
33111
- theme: [{ type: Input }],
33112
- icon: [{ type: Input }],
33113
- title: [{ type: Input }],
33114
- hasDialogue: [{ type: Input }],
33115
- link: [{ type: Input }],
33116
- isCloseable: [{ type: Input }],
33117
- message: [{ type: Input }],
33118
- closed: [{ type: Output }]
33119
- };
33120
-
33121
- // NG2
33122
- class NovoToastService {
33123
- constructor(componentUtils) {
33124
- this.componentUtils = componentUtils;
33125
- this.references = [];
33126
- this.icons = { default: 'bell', success: 'check', info: 'info', warning: 'warning', danger: 'remove' };
33127
- this.defaults = { hideDelay: 3500, position: 'growlTopRight', theme: 'default' };
33128
- }
33129
- set parentViewContainer(view) {
33130
- this._parentViewContainer = view;
33131
- }
33132
- alert(options, toastElement = NovoToastElement) {
33133
- return new Promise((resolve) => {
33134
- if (!this._parentViewContainer) {
33135
- console.error('No parent view container specified for the ToastService. Set it inside your main application. \nthis.toastService.parentViewContainer = view (ViewContainerRef)');
33136
- return;
33137
- }
33138
- const toast = this.componentUtils.append(toastElement, this._parentViewContainer);
33139
- this.references.push(toast);
33140
- this.handleAlert(toast.instance, options);
33141
- resolve(toast);
33142
- });
33143
- }
33144
- isVisible(toast) {
33145
- return toast.show;
33146
- }
33147
- hide(toast) {
33148
- toast.animate = false;
33149
- setTimeout(() => {
33150
- toast.show = false;
33151
- const REF = this.references.filter((x) => x.instance === toast)[0];
33152
- if (REF) {
33153
- this.references.splice(this.references.indexOf(REF), 1);
33154
- REF.destroy();
33155
- }
33156
- }, 300);
33157
- }
33158
- handleAlert(toast, options) {
33159
- this.setToastOnSession(toast, options);
33160
- setTimeout(() => {
33161
- this.show(toast);
33162
- }, 20);
33163
- if (!toast.isCloseable) {
33164
- this.toastTimer(toast);
33165
- }
33166
- }
33167
- setToastOnSession(toast, opts) {
33168
- const OPTIONS = typeof opts === 'object' ? opts : {};
33169
- toast.parent = this;
33170
- toast.title = OPTIONS.title || '';
33171
- toast.message = OPTIONS.message || '';
33172
- toast.hideDelay = OPTIONS.hideDelay || this.defaults.hideDelay;
33173
- toast.link = OPTIONS.link || '';
33174
- toast.isCloseable = OPTIONS.isCloseable || false;
33175
- const CUSTOM_CLASS = OPTIONS.customClass || '';
33176
- const ALERT_STYLE = OPTIONS.theme || this.defaults.theme;
33177
- const ALERT_POSITION = OPTIONS.position || this.defaults.position;
33178
- const ALERT_ICON = OPTIONS.icon || this.icons.default;
33179
- toast.iconClass = `bhi-${ALERT_ICON}`;
33180
- toast.launched = true;
33181
- toast.alertTheme = `${ALERT_STYLE} ${ALERT_POSITION} ${CUSTOM_CLASS} toast-container launched`;
33182
- }
33183
- show(toast) {
33184
- toast.show = true;
33185
- setTimeout(addClass, 25);
33186
- /**
33187
- * Adds animate class to be called after a timeout
33188
- **/
33189
- function addClass() {
33190
- toast.animate = true;
33191
- }
33192
- }
33193
- toastTimer(toast) {
33194
- if (toast.hideDelay < 0) {
33195
- return;
33196
- }
33197
- setTimeout(() => {
33198
- this.hide(toast);
33199
- }, toast.hideDelay);
33200
- }
33201
- }
33202
- NovoToastService.decorators = [
33203
- { type: Injectable }
33204
- ];
33205
- NovoToastService.ctorParameters = () => [
33206
- { type: ComponentUtils }
33207
- ];
33208
-
33209
33299
  // NG2
33210
33300
  class ControlConfirmModal {
33211
33301
  constructor(modalRef, params, labels) {
@@ -34972,7 +35062,7 @@ NovoControlTemplates.decorators = [
34972
35062
  <!--Date-->
34973
35063
  <ng-template novoTemplate="date" let-control let-form="form" let-errors="errors" let-methods="methods">
34974
35064
  <div [formGroup]="form" class="novo-control-input-container" [tooltip]="control.tooltip" [tooltipPosition]="control.tooltipPosition" [tooltipSize]="control?.tooltipSize" [tooltipPreline]="control?.tooltipPreline" [removeTooltipArrow]="control?.removeTooltipArrow" [tooltipAutoPosition]="control?.tooltipAutoPosition">
34975
- <novo-date-picker-input [attr.id]="control.key" [name]="control.key" [formControlName]="control.key" [start]="control.startDate" [end]="control.endDate" [format]="control.dateFormat" [allowInvalidDate]="control.allowInvalidDate" [textMaskEnabled]="control.textMaskEnabled" [placeholder]="control.placeholder" [weekStart]="control.weekStart" (focusEvent)="methods.handleFocus($event)" (blurEvent)="methods.handleBlur($event)" (changeEvent)="methods.emitChange($event)"></novo-date-picker-input>
35065
+ <novo-date-picker-input [attr.id]="control.key" [name]="control.key" [formControlName]="control.key" [start]="control.startDate" [end]="control.endDate" [disabledDateMessage]="control.disabledDateMessage" [format]="control.dateFormat" [allowInvalidDate]="control.allowInvalidDate" [textMaskEnabled]="control.textMaskEnabled" [placeholder]="control.placeholder" [weekStart]="control.weekStart" (focusEvent)="methods.handleFocus($event)" (blurEvent)="methods.handleBlur($event)" (changeEvent)="methods.emitChange($event)"></novo-date-picker-input>
34976
35066
  </div>
34977
35067
  </ng-template>
34978
35068