@memberjunction/ng-user-view-grid 2.48.0 → 2.50.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.
@@ -1,12 +1,3 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  import { Component, ViewChild, ElementRef, Output, EventEmitter, Input } from '@angular/core';
11
2
  import { Metadata, RunView, EntityFieldTSType, LogError, CompositeKey, PotentialDuplicateRequest, FieldValueCollection } from '@memberjunction/core';
12
3
  import { ViewInfo, ResourcePermissionEngine } from '@memberjunction/core-entities';
@@ -435,12 +426,94 @@ function UserViewGridComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
435
426
  i0.ɵɵproperty("DialogVisible", ctx_r1.showTemplatePreviewDialog)("entityInfo", ctx_r1._entityInfo)("runViewParams", ctx_r1.Params);
436
427
  } }
437
428
  export class UserViewGridComponent {
429
+ elementRef;
430
+ formBuilder;
431
+ router;
432
+ renderer;
433
+ title = 'UserViewGrid';
434
+ /**
435
+ * Parameters for running the view
436
+ */
437
+ Params;
438
+ BottomMargin = 0;
439
+ InEditMode = false;
440
+ EditMode = "None";
441
+ AutoNavigate = true;
442
+ /**
443
+ * If you enable the ShowCreateNewRecordButton and the user has permission, when they click the New button, these values from this object will auto-populate the new record form
444
+ */
445
+ NewRecordValues;
446
+ /**
447
+ * If set to true, the Create New Record button will be displayed if the user is allowed to create new records for the entity being shown. If set to false, the Create New Record button will be hidden.
448
+ */
449
+ ShowCreateNewRecordButton = true;
450
+ /**
451
+ * If set to true, any Actions that are linked to the displayed entity via EntityActions that have an InvocationContext for Views will be shown.
452
+ */
453
+ ShowEntityActionButtons = true;
454
+ /**
455
+ * If set to true, and if the entity being displayed supports communication, the communication button will be displayed. If set to false, the communication button will be hidden.
456
+ */
457
+ ShowCommunicationButton = true;
458
+ /**
459
+ * When set to Dialog, the Create New Record button will open a dialog to create a new record. When set to Tab, the Create New Record button will open a new tab to create a new record.
460
+ */
461
+ CreateRecordMode = "Tab";
462
+ rowClicked = new EventEmitter();
463
+ rowEdited = new EventEmitter();
464
+ kendoGridElement = null;
465
+ kendoGridElementRef = null;
466
+ kendoExcelExport = null;
467
+ recordCompareComponent = null;
468
+ analysisQuestion = null;
469
+ analysisResults = null;
470
+ compareDialogContainer;
471
+ _pendingRecords = [];
472
+ viewData = [];
473
+ totalRowCount = 0;
474
+ formattedData = [];
475
+ viewColumns = [];
476
+ visibleColumns = [];
477
+ sortSettings = [];
478
+ entityRecord = null;
479
+ skip = 0;
480
+ pageSize = 40;
481
+ isLoading = false;
482
+ neverLoaded = true;
483
+ gridView = { data: [], total: 0 };
484
+ gridHeight = 750;
485
+ _viewEntity;
486
+ _entityInfo;
487
+ _newGridState = {};
488
+ editModeEnded = new Subject();
489
+ searchDebounce$ = new Subject();
490
+ recordsToCompare = [];
491
+ compareMode = false;
492
+ mergeMode = false;
493
+ duplicateMode = false;
494
+ addToListMode = false;
438
495
  get anyModeEnabled() {
439
496
  return this.compareMode || this.mergeMode || this.duplicateMode || this.addToListMode;
440
497
  }
441
498
  get EntityInfo() {
442
499
  return this._entityInfo;
443
500
  }
501
+ showNewRecordDialog = false;
502
+ selectableSettings = {
503
+ enabled: false
504
+ };
505
+ selectedKeys = [];
506
+ isCompareDialogOpened = false;
507
+ isConfirmDialogOpen = false;
508
+ showRefreshButton = true;
509
+ viewExecutionTime = 0;
510
+ showAddToListDialog = false;
511
+ showAddToListLoader = false;
512
+ sourceListEntities = null;
513
+ listEntities = [];
514
+ selectedListEntities = [];
515
+ listEntitySearch = '';
516
+ EntityActions = [];
444
517
  get PendingRecords() {
445
518
  return this._pendingRecords;
446
519
  }
@@ -470,11 +543,10 @@ export class UserViewGridComponent {
470
543
  this.editModeEnded.next();
471
544
  }
472
545
  EditingComplete() {
473
- var _a, _b;
474
546
  if (this.InEditMode) {
475
547
  // tell our grid to close the cell that is currently being edited
476
- (_a = this.kendoGridElement) === null || _a === void 0 ? void 0 : _a.closeCell();
477
- (_b = this.kendoGridElement) === null || _b === void 0 ? void 0 : _b.closeRow(); // close the row too
548
+ this.kendoGridElement?.closeCell();
549
+ this.kendoGridElement?.closeRow(); // close the row too
478
550
  // we need to wait for edit mode to end before we can return true
479
551
  return new Promise((resolve, reject) => {
480
552
  const subscription = this.editModeEnded.subscribe(() => {
@@ -493,6 +565,10 @@ export class UserViewGridComponent {
493
565
  this.skip = event.skip;
494
566
  this.virtualLoadData();
495
567
  }
568
+ data = [
569
+ { text: "Folder" },
570
+ { text: "Report with Skip" },
571
+ ];
496
572
  virtualLoadData() {
497
573
  // check to see if we have already formatted the slice of the data we need right now
498
574
  // we are storing the formattted data in the formattedData array and it has same set
@@ -550,94 +626,15 @@ export class UserViewGridComponent {
550
626
  this.formBuilder = formBuilder;
551
627
  this.router = router;
552
628
  this.renderer = renderer;
553
- this.title = 'UserViewGrid';
554
- this.BottomMargin = 0;
555
- this.InEditMode = false;
556
- this.EditMode = "None";
557
- this.AutoNavigate = true;
558
- /**
559
- * If set to true, the Create New Record button will be displayed if the user is allowed to create new records for the entity being shown. If set to false, the Create New Record button will be hidden.
560
- */
561
- this.ShowCreateNewRecordButton = true;
562
- /**
563
- * If set to true, any Actions that are linked to the displayed entity via EntityActions that have an InvocationContext for Views will be shown.
564
- */
565
- this.ShowEntityActionButtons = true;
566
- /**
567
- * If set to true, and if the entity being displayed supports communication, the communication button will be displayed. If set to false, the communication button will be hidden.
568
- */
569
- this.ShowCommunicationButton = true;
570
- /**
571
- * When set to Dialog, the Create New Record button will open a dialog to create a new record. When set to Tab, the Create New Record button will open a new tab to create a new record.
572
- */
573
- this.CreateRecordMode = "Tab";
574
- this.rowClicked = new EventEmitter();
575
- this.rowEdited = new EventEmitter();
576
- this.kendoGridElement = null;
577
- this.kendoGridElementRef = null;
578
- this.kendoExcelExport = null;
579
- this.recordCompareComponent = null;
580
- this.analysisQuestion = null;
581
- this.analysisResults = null;
582
- this._pendingRecords = [];
583
- this.viewData = [];
584
- this.totalRowCount = 0;
585
- this.formattedData = [];
586
- this.viewColumns = [];
587
- this.visibleColumns = [];
588
- this.sortSettings = [];
589
- this.entityRecord = null;
590
- this.skip = 0;
591
- this.pageSize = 40;
592
- this.isLoading = false;
593
- this.neverLoaded = true;
594
- this.gridView = { data: [], total: 0 };
595
- this.gridHeight = 750;
596
- this._newGridState = {};
597
- this.editModeEnded = new Subject();
598
- this.searchDebounce$ = new Subject();
599
- this.recordsToCompare = [];
600
- this.compareMode = false;
601
- this.mergeMode = false;
602
- this.duplicateMode = false;
603
- this.addToListMode = false;
604
- this.showNewRecordDialog = false;
605
- this.selectableSettings = {
606
- enabled: false
607
- };
608
- this.selectedKeys = [];
609
- this.isCompareDialogOpened = false;
610
- this.isConfirmDialogOpen = false;
611
- this.showRefreshButton = true;
612
- this.viewExecutionTime = 0;
613
- this.showAddToListDialog = false;
614
- this.showAddToListLoader = false;
615
- this.sourceListEntities = null;
616
- this.listEntities = [];
617
- this.selectedListEntities = [];
618
- this.listEntitySearch = '';
619
- this.EntityActions = [];
620
- this.data = [
621
- { text: "Folder" },
622
- { text: "Report with Skip" },
623
- ];
624
- this._viewDirty = false;
625
- this._movedToBody = false;
626
- this._deferLoadCount = 0;
627
- this._allowLoad = true;
628
- // Export Functionality
629
- this.exportColumns = [];
630
- this.exportData = [];
631
- this.showTemplatePreviewDialog = false;
632
- this.entityFormDialog = null;
633
629
  }
630
+ _saveTimeout;
634
631
  SaveView() {
635
632
  // debounced outer function...
636
633
  clearTimeout(this._saveTimeout);
637
- this._saveTimeout = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
634
+ this._saveTimeout = setTimeout(async () => {
638
635
  // when we actually call inner save view we do await
639
- yield this.innerSaveView();
640
- }), 5000); // 5 seconds delay
636
+ await this.innerSaveView();
637
+ }, 5000); // 5 seconds delay
641
638
  }
642
639
  ;
643
640
  get UserCanEdit() {
@@ -652,38 +649,37 @@ export class UserViewGridComponent {
652
649
  else
653
650
  return false;
654
651
  }
655
- innerSaveView() {
656
- return __awaiter(this, void 0, void 0, function* () {
657
- if (this._viewDirty) {
658
- const md = new Metadata();
659
- if (this._viewEntity &&
660
- this._viewEntity.UserCanEdit) {
661
- // this view is a saved view, AND it belongs to the current user
662
- // update the grid state if we have settings updates for columns and/or sorts
663
- const tempGridState = JSON.parse(this._viewEntity.Get('GridState'));
664
- const tempColSettings = this._newGridState.columnSettings ? this._newGridState.columnSettings : tempGridState.columnSettings;
665
- tempColSettings.forEach((col) => { col.DisplayName, col.ID, col.Name, col.hidden, col.orderIndex, col.width; }); // remove EntityFieldInfo from the column settings
666
- tempGridState.columnSettings = tempColSettings;
667
- tempGridState.sortSettings = this._newGridState.sortSettings ? this._newGridState.sortSettings : tempGridState.sortSettings;
668
- // now stringify the grid state and save it
669
- this._viewEntity.Set('GridState', JSON.stringify(tempGridState));
670
- const newSortState = tempGridState.sortSettings ? tempGridState.sortSettings.map((s) => { return { field: s.field, direction: s.dir }; }) : [];
671
- const oldSortState = JSON.parse(this._viewEntity.Get('SortState'));
672
- this._viewEntity.Set('SortState', JSON.stringify(newSortState));
673
- if (yield this._viewEntity.Save()) {
674
- // check to see if sort state changed and if so, refresh the grid
675
- if (JSON.stringify(newSortState) !== JSON.stringify(oldSortState)) {
676
- if (this.Params) // makes sure we have params before we refresh
677
- this.Refresh(this.Params);
678
- }
679
- this._viewDirty = false;
680
- }
681
- else {
682
- this.CreateSimpleNotification('Unable to save view settings', 'error', 5000);
652
+ _viewDirty = false;
653
+ async innerSaveView() {
654
+ if (this._viewDirty) {
655
+ const md = new Metadata();
656
+ if (this._viewEntity &&
657
+ this._viewEntity.UserCanEdit) {
658
+ // this view is a saved view, AND it belongs to the current user
659
+ // update the grid state if we have settings updates for columns and/or sorts
660
+ const tempGridState = JSON.parse(this._viewEntity.Get('GridState'));
661
+ const tempColSettings = this._newGridState.columnSettings ? this._newGridState.columnSettings : tempGridState.columnSettings;
662
+ tempColSettings.forEach((col) => { col.DisplayName, col.ID, col.Name, col.hidden, col.orderIndex, col.width; }); // remove EntityFieldInfo from the column settings
663
+ tempGridState.columnSettings = tempColSettings;
664
+ tempGridState.sortSettings = this._newGridState.sortSettings ? this._newGridState.sortSettings : tempGridState.sortSettings;
665
+ // now stringify the grid state and save it
666
+ this._viewEntity.Set('GridState', JSON.stringify(tempGridState));
667
+ const newSortState = tempGridState.sortSettings ? tempGridState.sortSettings.map((s) => { return { field: s.field, direction: s.dir }; }) : [];
668
+ const oldSortState = JSON.parse(this._viewEntity.Get('SortState'));
669
+ this._viewEntity.Set('SortState', JSON.stringify(newSortState));
670
+ if (await this._viewEntity.Save()) {
671
+ // check to see if sort state changed and if so, refresh the grid
672
+ if (JSON.stringify(newSortState) !== JSON.stringify(oldSortState)) {
673
+ if (this.Params) // makes sure we have params before we refresh
674
+ this.Refresh(this.Params);
683
675
  }
676
+ this._viewDirty = false;
677
+ }
678
+ else {
679
+ this.CreateSimpleNotification('Unable to save view settings', 'error', 5000);
684
680
  }
685
681
  }
686
- });
682
+ }
687
683
  }
688
684
  CreateSimpleNotification(message, style, duration) {
689
685
  const data = {
@@ -698,139 +694,130 @@ export class UserViewGridComponent {
698
694
  args: data
699
695
  });
700
696
  }
701
- columnReorder(args) {
702
- return __awaiter(this, void 0, void 0, function* () {
703
- // Remove the column from the original position
704
- // need to find the column in the viewColumns array because args.old/new Indexes are from the visibleColumns array
705
- const fieldName = args.column.field;
706
- if (fieldName) {
707
- const vcOldIndex = this.viewColumns.findIndex((vc) => vc.Name === fieldName);
708
- const vcNewIndex = this.viewColumns.findIndex((vc) => vc.orderIndex === args.newIndex);
709
- if (vcOldIndex >= 0) {
710
- // got the index, now remove the element
711
- const element = this.viewColumns.splice(vcOldIndex, 1)[0];
712
- // Insert it at the new position
713
- this.viewColumns.splice(vcNewIndex, 0, element);
714
- // go through all of the columns and set orderIndex as that isn't done automatically
715
- let visColIndex = 0;
716
- for (let i = 0; i < this.viewColumns.length; i++) {
717
- if (!this.viewColumns[i].hidden) {
718
- this.viewColumns[i].orderIndex = visColIndex;
719
- visColIndex++;
720
- }
697
+ async columnReorder(args) {
698
+ // Remove the column from the original position
699
+ // need to find the column in the viewColumns array because args.old/new Indexes are from the visibleColumns array
700
+ const fieldName = args.column.field;
701
+ if (fieldName) {
702
+ const vcOldIndex = this.viewColumns.findIndex((vc) => vc.Name === fieldName);
703
+ const vcNewIndex = this.viewColumns.findIndex((vc) => vc.orderIndex === args.newIndex);
704
+ if (vcOldIndex >= 0) {
705
+ // got the index, now remove the element
706
+ const element = this.viewColumns.splice(vcOldIndex, 1)[0];
707
+ // Insert it at the new position
708
+ this.viewColumns.splice(vcNewIndex, 0, element);
709
+ // go through all of the columns and set orderIndex as that isn't done automatically
710
+ let visColIndex = 0;
711
+ for (let i = 0; i < this.viewColumns.length; i++) {
712
+ if (!this.viewColumns[i].hidden) {
713
+ this.viewColumns[i].orderIndex = visColIndex;
714
+ visColIndex++;
721
715
  }
722
- // now loop through all of the HIDDEN columns and set their orderIndex, done in second loop because we want first loop to give us total number of visible columns
723
- for (let i = 0; i < this.viewColumns.length; i++) {
724
- if (this.viewColumns[i].hidden) {
725
- this.viewColumns[i].orderIndex = visColIndex;
726
- visColIndex++;
727
- }
716
+ }
717
+ // now loop through all of the HIDDEN columns and set their orderIndex, done in second loop because we want first loop to give us total number of visible columns
718
+ for (let i = 0; i < this.viewColumns.length; i++) {
719
+ if (this.viewColumns[i].hidden) {
720
+ this.viewColumns[i].orderIndex = visColIndex;
721
+ visColIndex++;
728
722
  }
729
- // make sure that _newGridState.columnSettings is set
730
- this._newGridState.columnSettings = this.viewColumns;
731
- this._viewDirty = true;
732
- this.SaveView();
733
723
  }
724
+ // make sure that _newGridState.columnSettings is set
725
+ this._newGridState.columnSettings = this.viewColumns;
726
+ this._viewDirty = true;
727
+ this.SaveView();
734
728
  }
735
- });
729
+ }
736
730
  }
737
- columnResize(args) {
738
- return __awaiter(this, void 0, void 0, function* () {
739
- for (const col of args) {
740
- const c = col.column;
741
- const viewCol = this.viewColumns.find(vc => vc.Name === c.field);
742
- if (viewCol)
743
- viewCol.width = col.newWidth;
744
- }
745
- this._newGridState.columnSettings = this.viewColumns.map(vc => {
746
- return {
747
- Name: vc.Name,
748
- DisplayName: vc.DisplayName,
749
- width: vc.width,
750
- orderIndex: vc.orderIndex,
751
- hidden: vc.hidden
752
- };
753
- });
754
- this._viewDirty = true;
755
- this.SaveView();
731
+ async columnResize(args) {
732
+ for (const col of args) {
733
+ const c = col.column;
734
+ const viewCol = this.viewColumns.find(vc => vc.Name === c.field);
735
+ if (viewCol)
736
+ viewCol.width = col.newWidth;
737
+ }
738
+ this._newGridState.columnSettings = this.viewColumns.map(vc => {
739
+ return {
740
+ Name: vc.Name,
741
+ DisplayName: vc.DisplayName,
742
+ width: vc.width,
743
+ orderIndex: vc.orderIndex,
744
+ hidden: vc.hidden
745
+ };
756
746
  });
747
+ this._viewDirty = true;
748
+ this.SaveView();
757
749
  }
758
- sortChanged(sort) {
759
- return __awaiter(this, void 0, void 0, function* () {
760
- if (sort && sort.length > 0) {
761
- // remove any sort settings that don't have a direction
762
- const filterSort = sort.filter((s) => s.dir !== undefined && s.dir !== null && s.dir !== "");
763
- this._newGridState.sortSettings = filterSort;
764
- }
765
- else
766
- this._newGridState.sortSettings = sort;
767
- this.sortSettings = this._newGridState.sortSettings; // for the UI display - grid binding to this shows that the sort is applied via arrows in the column headers
768
- if (this.IsDynamicView()) {
769
- // Dynamic View, we have this.Params and can add an OrderBy and then just Refresh() the entire component
770
- // that will result in going to the server for a refreshed set of data
771
- if (this.Params) {
772
- this.Params.OrderBy = sort[0].field + ' ' + (sort[0].dir);
773
- this.Refresh(this.Params);
774
- }
775
- else {
776
- LogError("sortChanged() called but this.Params is null or undefined"); // should never get here
777
- }
750
+ async sortChanged(sort) {
751
+ if (sort && sort.length > 0) {
752
+ // remove any sort settings that don't have a direction
753
+ const filterSort = sort.filter((s) => s.dir !== undefined && s.dir !== null && s.dir !== "");
754
+ this._newGridState.sortSettings = filterSort;
755
+ }
756
+ else
757
+ this._newGridState.sortSettings = sort;
758
+ this.sortSettings = this._newGridState.sortSettings; // for the UI display - grid binding to this shows that the sort is applied via arrows in the column headers
759
+ if (this.IsDynamicView()) {
760
+ // Dynamic View, we have this.Params and can add an OrderBy and then just Refresh() the entire component
761
+ // that will result in going to the server for a refreshed set of data
762
+ if (this.Params) {
763
+ this.Params.OrderBy = sort[0].field + ' ' + (sort[0].dir);
764
+ this.Refresh(this.Params);
778
765
  }
779
766
  else {
780
- // Saved view - we do this on the server side only
781
- this._viewDirty = true;
782
- this.innerSaveView(); // for sort changes we call innerSaveView() directly, not through SaveView() which is debounced
767
+ LogError("sortChanged() called but this.Params is null or undefined"); // should never get here
783
768
  }
784
- });
769
+ }
770
+ else {
771
+ // Saved view - we do this on the server side only
772
+ this._viewDirty = true;
773
+ this.innerSaveView(); // for sort changes we call innerSaveView() directly, not through SaveView() which is debounced
774
+ }
785
775
  }
786
- cellClickHandler(args) {
787
- return __awaiter(this, void 0, void 0, function* () {
788
- if (this.compareMode || this.mergeMode) {
789
- return;
790
- }
791
- if (!this._entityInfo) {
792
- LogError("cellClickHandler() called but this._entityInfo is null or undefined");
793
- return;
776
+ async cellClickHandler(args) {
777
+ if (this.compareMode || this.mergeMode) {
778
+ return;
779
+ }
780
+ if (!this._entityInfo) {
781
+ LogError("cellClickHandler() called but this._entityInfo is null or undefined");
782
+ return;
783
+ }
784
+ const compositeKey = new CompositeKey();
785
+ compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, this.viewData[args.rowIndex]);
786
+ this.rowClicked.emit({
787
+ entityId: this._entityInfo.ID,
788
+ entityName: this._entityInfo.Name,
789
+ CompositeKey: compositeKey
790
+ });
791
+ if (this._entityInfo.AllowUpdateAPI && this.EditMode !== "None") {
792
+ const perm = this._entityInfo.GetUserPermisions(new Metadata().CurrentUser);
793
+ if (perm.CanUpdate) {
794
+ this.StartEditMode();
795
+ args.sender.editCell(args.rowIndex, args.columnIndex, this.createFormGroup(args.dataItem));
794
796
  }
795
- const compositeKey = new CompositeKey();
796
- compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, this.viewData[args.rowIndex]);
797
- this.rowClicked.emit({
798
- entityId: this._entityInfo.ID,
799
- entityName: this._entityInfo.Name,
800
- CompositeKey: compositeKey
801
- });
802
- if (this._entityInfo.AllowUpdateAPI && this.EditMode !== "None") {
803
- const perm = this._entityInfo.GetUserPermisions(new Metadata().CurrentUser);
804
- if (perm.CanUpdate) {
805
- this.StartEditMode();
806
- args.sender.editCell(args.rowIndex, args.columnIndex, this.createFormGroup(args.dataItem));
807
- }
797
+ }
798
+ if (this.EditMode === 'None' && this.AutoNavigate) {
799
+ // tell app router to go to this record
800
+ let decodedUrl = decodeURIComponent(this.router.url).slice(1);
801
+ if (decodedUrl.includes('?')) {
802
+ decodedUrl = decodedUrl.split('?')[0];
808
803
  }
809
- if (this.EditMode === 'None' && this.AutoNavigate) {
810
- // tell app router to go to this record
811
- let decodedUrl = decodeURIComponent(this.router.url).slice(1);
812
- if (decodedUrl.includes('?')) {
813
- decodedUrl = decodedUrl.split('?')[0];
814
- }
815
- const newURL = ['resource', 'record', compositeKey.ToURLSegment()];
816
- const newURLString = newURL.join('/');
817
- if (newURLString === decodedUrl) {
818
- // we have to force the router to change its state otherwise the next line below won't do anything because the
819
- // router thinks it is the same URL, since we have the Entity on the query params, we can just change the URL to something else
820
- // and skipLocationChange so that the browser history doesn't get messed up
821
- yield this.router.navigateByUrl('/dummy', { skipLocationChange: true });
822
- }
823
- this.router.navigate(newURL, { queryParams: { Entity: this._entityInfo.Name } });
804
+ const newURL = ['resource', 'record', compositeKey.ToURLSegment()];
805
+ const newURLString = newURL.join('/');
806
+ if (newURLString === decodedUrl) {
807
+ // we have to force the router to change its state otherwise the next line below won't do anything because the
808
+ // router thinks it is the same URL, since we have the Entity on the query params, we can just change the URL to something else
809
+ // and skipLocationChange so that the browser history doesn't get messed up
810
+ await this.router.navigateByUrl('/dummy', { skipLocationChange: true });
824
811
  }
825
- });
812
+ this.router.navigate(newURL, { queryParams: { Entity: this._entityInfo.Name } });
813
+ }
826
814
  }
827
815
  createFormGroup(dataItem) {
828
816
  const groupFields = {};
829
817
  this.viewColumns.forEach((vc) => {
830
- var _a, _b, _c;
831
- if (((_a = vc.EntityField) === null || _a === void 0 ? void 0 : _a.AllowUpdateAPI) &&
832
- ((_b = vc.EntityField) === null || _b === void 0 ? void 0 : _b.IsVirtual) === false &&
833
- ((_c = vc.EntityField) === null || _c === void 0 ? void 0 : _c.AllowUpdateInView))
818
+ if (vc.EntityField?.AllowUpdateAPI &&
819
+ vc.EntityField?.IsVirtual === false &&
820
+ vc.EntityField?.AllowUpdateInView)
834
821
  groupFields[vc.Name] = dataItem[vc.Name];
835
822
  });
836
823
  return this.formBuilder.group(groupFields);
@@ -847,80 +834,77 @@ export class UserViewGridComponent {
847
834
  return "text";
848
835
  }
849
836
  }
850
- cellCloseHandler(args) {
851
- return __awaiter(this, void 0, void 0, function* () {
852
- var _a;
853
- try {
854
- if (this._entityInfo && this.EditMode !== "None") {
855
- const { formGroup, dataItem, column } = args;
856
- if (!formGroup.valid) {
857
- // prevent closing the edited cell if there are invalid values.
858
- args.preventDefault();
837
+ async cellCloseHandler(args) {
838
+ try {
839
+ if (this._entityInfo && this.EditMode !== "None") {
840
+ const { formGroup, dataItem, column } = args;
841
+ if (!formGroup.valid) {
842
+ // prevent closing the edited cell if there are invalid values.
843
+ args.preventDefault();
844
+ }
845
+ else if (formGroup.dirty) {
846
+ if (args.originalEvent && args.originalEvent.keyCode === Keys.Escape) {
847
+ return; // user hit escape, so don't save their changes
859
848
  }
860
- else if (formGroup.dirty) {
861
- if (args.originalEvent && args.originalEvent.keyCode === Keys.Escape) {
862
- return; // user hit escape, so don't save their changes
863
- }
864
- // update the data item with the new values - this drives UI refresh while we save the record...
865
- Object.assign(dataItem, formGroup.value);
866
- const md = new Metadata();
867
- let record;
868
- let bSaved = false;
869
- if (this.EditMode === "Save") {
849
+ // update the data item with the new values - this drives UI refresh while we save the record...
850
+ Object.assign(dataItem, formGroup.value);
851
+ const md = new Metadata();
852
+ let record;
853
+ let bSaved = false;
854
+ if (this.EditMode === "Save") {
855
+ let compositeKey = new CompositeKey();
856
+ compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, dataItem);
857
+ record = await md.GetEntityObject(this._entityInfo.Name);
858
+ await record.InnerLoad(compositeKey);
859
+ record.SetMany(formGroup.value);
860
+ bSaved = await record.Save();
861
+ // if (!bSaved)
862
+ // this.CreateSimpleNotification("Error saving record: " + record.Get(pkey), 'error', 5000)
863
+ }
864
+ else {
865
+ record = this._pendingRecords.find((r) => {
866
+ // match on all columns within the primary key of the entity using the
867
+ // _entityInfo object to get the primary key fields
868
+ const noMatch = this._entityInfo.PrimaryKeys.some((ef) => {
869
+ return r.record.Get(ef.Name) !== dataItem[ef.Name];
870
+ });
871
+ // noMatch will be true if any of the primary key fields don't match
872
+ return !noMatch;
873
+ })?.record;
874
+ if (!record) {
875
+ // haven't edited this one before
876
+ record = await md.GetEntityObject(this._viewEntity.Get('Entity'));
870
877
  let compositeKey = new CompositeKey();
871
878
  compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, dataItem);
872
- record = yield md.GetEntityObject(this._entityInfo.Name);
873
- yield record.InnerLoad(compositeKey);
874
- record.SetMany(formGroup.value);
875
- bSaved = yield record.Save();
876
- // if (!bSaved)
877
- // this.CreateSimpleNotification("Error saving record: " + record.Get(pkey), 'error', 5000)
879
+ await record.InnerLoad(compositeKey);
880
+ this._pendingRecords.push({ record,
881
+ row: args.rowIndex,
882
+ dataItem }); // don't save - put the changed record on a queue for saving later by our container
878
883
  }
879
- else {
880
- record = (_a = this._pendingRecords.find((r) => {
881
- // match on all columns within the primary key of the entity using the
882
- // _entityInfo object to get the primary key fields
883
- const noMatch = this._entityInfo.PrimaryKeys.some((ef) => {
884
- return r.record.Get(ef.Name) !== dataItem[ef.Name];
885
- });
886
- // noMatch will be true if any of the primary key fields don't match
887
- return !noMatch;
888
- })) === null || _a === void 0 ? void 0 : _a.record;
889
- if (!record) {
890
- // haven't edited this one before
891
- record = yield md.GetEntityObject(this._viewEntity.Get('Entity'));
892
- let compositeKey = new CompositeKey();
893
- compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, dataItem);
894
- yield record.InnerLoad(compositeKey);
895
- this._pendingRecords.push({ record,
896
- row: args.rowIndex,
897
- dataItem }); // don't save - put the changed record on a queue for saving later by our container
898
- }
899
- // now, based on the column that we're in, update the record with the new value
900
- record.Set(column.field, formGroup.value[column.field]);
901
- // if a boolean value, modify what is in the grid so it is formatted properly
902
- if (column.field && column.field.length > 0) {
903
- const ef = this._entityInfo.Fields.find(f => f.Name === column.field);
904
- if (ef && ef.TSType === EntityFieldTSType.Boolean) {
905
- dataItem[column.field] = record.Get(column.field) ? '✓' : '';
906
- }
884
+ // now, based on the column that we're in, update the record with the new value
885
+ record.Set(column.field, formGroup.value[column.field]);
886
+ // if a boolean value, modify what is in the grid so it is formatted properly
887
+ if (column.field && column.field.length > 0) {
888
+ const ef = this._entityInfo.Fields.find(f => f.Name === column.field);
889
+ if (ef && ef.TSType === EntityFieldTSType.Boolean) {
890
+ dataItem[column.field] = record.Get(column.field) ? '✓' : '';
907
891
  }
908
892
  }
909
- this.rowEdited.emit({
910
- record: record,
911
- row: args.rowIndex,
912
- saved: bSaved
913
- });
914
893
  }
894
+ this.rowEdited.emit({
895
+ record: record,
896
+ row: args.rowIndex,
897
+ saved: bSaved
898
+ });
915
899
  }
916
900
  }
917
- catch (e) {
918
- console.error(e);
919
- }
920
- finally {
921
- this.EndEditMode();
922
- }
923
- });
901
+ }
902
+ catch (e) {
903
+ console.error(e);
904
+ }
905
+ finally {
906
+ this.EndEditMode();
907
+ }
924
908
  }
925
909
  // this handles reverting pending cahnges to records WITHIN the grid, not the user view settings, unrelated to that.
926
910
  RevertPendingChanges() {
@@ -936,44 +920,43 @@ export class UserViewGridComponent {
936
920
  }
937
921
  ngOnInit() {
938
922
  }
939
- ngAfterViewInit() {
940
- return __awaiter(this, void 0, void 0, function* () {
941
- yield ResourcePermissionEngine.Instance.Config();
942
- //this.setGridHeight();
943
- if (this.Params)
944
- this.Refresh(this.Params);
945
- // setup event listener for MJGlobal because we might have a parent component that sends us messages
946
- MJGlobal.Instance.GetEventListener(false).subscribe((e) => {
947
- switch (e.event) {
948
- case MJEventType.ComponentEvent:
949
- if (e.eventCode === BaseFormComponentEventCodes.BASE_CODE) {
950
- // we have an event from a BaseFormComponent, now we need to determine if WE are a descendant of that component
951
- const event = e.args;
952
- if (SharedService.IsDescendant(event.elementRef, this.elementRef)) {
953
- // we are a descendant of the component that sent the event, so we need to handle it
954
- switch (event.subEventCode) {
955
- case BaseFormComponentEventCodes.EDITING_COMPLETE:
956
- this.EditingComplete();
957
- break;
958
- case BaseFormComponentEventCodes.REVERT_PENDING_CHANGES:
959
- this.RevertPendingChanges();
960
- break;
961
- case BaseFormComponentEventCodes.POPULATE_PENDING_RECORDS:
962
- // provide all of our pending records back to the caller
963
- this.PendingRecords.forEach((r) => {
964
- const edEvent = event;
965
- const p = { entityObject: r.record, action: 'save' };
966
- edEvent.pendingChanges.push(p);
967
- });
968
- break;
969
- }
923
+ async ngAfterViewInit() {
924
+ await ResourcePermissionEngine.Instance.Config();
925
+ //this.setGridHeight();
926
+ if (this.Params)
927
+ this.Refresh(this.Params);
928
+ // setup event listener for MJGlobal because we might have a parent component that sends us messages
929
+ MJGlobal.Instance.GetEventListener(false).subscribe((e) => {
930
+ switch (e.event) {
931
+ case MJEventType.ComponentEvent:
932
+ if (e.eventCode === BaseFormComponentEventCodes.BASE_CODE) {
933
+ // we have an event from a BaseFormComponent, now we need to determine if WE are a descendant of that component
934
+ const event = e.args;
935
+ if (SharedService.IsDescendant(event.elementRef, this.elementRef)) {
936
+ // we are a descendant of the component that sent the event, so we need to handle it
937
+ switch (event.subEventCode) {
938
+ case BaseFormComponentEventCodes.EDITING_COMPLETE:
939
+ this.EditingComplete();
940
+ break;
941
+ case BaseFormComponentEventCodes.REVERT_PENDING_CHANGES:
942
+ this.RevertPendingChanges();
943
+ break;
944
+ case BaseFormComponentEventCodes.POPULATE_PENDING_RECORDS:
945
+ // provide all of our pending records back to the caller
946
+ this.PendingRecords.forEach((r) => {
947
+ const edEvent = event;
948
+ const p = { entityObject: r.record, action: 'save' };
949
+ edEvent.pendingChanges.push(p);
950
+ });
951
+ break;
970
952
  }
971
953
  }
972
- break;
973
- }
974
- });
954
+ }
955
+ break;
956
+ }
975
957
  });
976
958
  }
959
+ _movedToBody = false;
977
960
  moveDialogToBody() {
978
961
  if (this._movedToBody)
979
962
  return;
@@ -981,6 +964,8 @@ export class UserViewGridComponent {
981
964
  this.renderer.appendChild(document.body, dialogElement);
982
965
  this._movedToBody = true;
983
966
  }
967
+ _deferLoadCount = 0;
968
+ _allowLoad = true;
984
969
  get AllowLoad() {
985
970
  return this._allowLoad;
986
971
  }
@@ -992,126 +977,121 @@ export class UserViewGridComponent {
992
977
  this.Refresh(this.Params);
993
978
  }
994
979
  }
995
- RefreshFromSavedParams() {
996
- return __awaiter(this, void 0, void 0, function* () {
997
- if (this.Params)
998
- this.Refresh(this.Params);
999
- });
980
+ async RefreshFromSavedParams() {
981
+ if (this.Params)
982
+ this.Refresh(this.Params);
1000
983
  }
1001
- Refresh(params) {
1002
- return __awaiter(this, void 0, void 0, function* () {
1003
- var _a, _b, _c;
1004
- this.Params = params;
1005
- if (this.AllowLoad === false) { // MUST DO THIS IMMEDIATELY AFTER STORING PARAMS SO THAT IT IS NOT ASYNC FROM HERE - THAT WAY WE GET FUTURE CALLS TO Refresh() when AllowLoad is set to TRUE
1006
- return;
984
+ async Refresh(params) {
985
+ this.Params = params;
986
+ if (this.AllowLoad === false) { // MUST DO THIS IMMEDIATELY AFTER STORING PARAMS SO THAT IT IS NOT ASYNC FROM HERE - THAT WAY WE GET FUTURE CALLS TO Refresh() when AllowLoad is set to TRUE
987
+ return;
988
+ }
989
+ // NOW WE CAN DO ASYNC stuff, before we check AllowLoad we must not do async stuff
990
+ await TemplateEngineBase.Instance.Config(false);
991
+ await EntityCommunicationsEngineClient.Instance.Config(false);
992
+ await CommunicationEngineBase.Instance.Config(false);
993
+ await EntityActionEngineBase.Instance.Config(false);
994
+ if (params && (params.ViewEntity || params.ViewID || params.ViewName || (params.EntityName && params.ExtraFilter))) {
995
+ const startTime = new Date().getTime();
996
+ this.isLoading = true;
997
+ this.neverLoaded = false;
998
+ const md = new Metadata();
999
+ const rv = new RunView();
1000
+ // get the view entity first so we can pass it in, otherwise it will end up getting loaded inside of RunView() which is inefficient as we need it too
1001
+ // this is done for performance purposes
1002
+ if (params.ViewEntity) {
1003
+ // When we receive the .ViewEntity via our params that is a time saver as we don't need to load it again, so ALWAYS use that instance of the entity object for the view entity
1004
+ this._viewEntity = params.ViewEntity;
1005
+ const e = md.Entities.find(x => x.ID === this._viewEntity?.EntityID);
1006
+ if (e)
1007
+ this._entityInfo = e;
1008
+ else
1009
+ throw new Error("Unable to get entity info for view: " + this._viewEntity?.Name);
1007
1010
  }
1008
- // NOW WE CAN DO ASYNC stuff, before we check AllowLoad we must not do async stuff
1009
- yield TemplateEngineBase.Instance.Config(false);
1010
- yield EntityCommunicationsEngineClient.Instance.Config(false);
1011
- yield CommunicationEngineBase.Instance.Config(false);
1012
- yield EntityActionEngineBase.Instance.Config(false);
1013
- if (params && (params.ViewEntity || params.ViewID || params.ViewName || (params.EntityName && params.ExtraFilter))) {
1014
- const startTime = new Date().getTime();
1015
- this.isLoading = true;
1016
- this.neverLoaded = false;
1017
- const md = new Metadata();
1018
- const rv = new RunView();
1019
- // get the view entity first so we can pass it in, otherwise it will end up getting loaded inside of RunView() which is inefficient as we need it too
1020
- // this is done for performance purposes
1021
- if (params.ViewEntity) {
1022
- // When we receive the .ViewEntity via our params that is a time saver as we don't need to load it again, so ALWAYS use that instance of the entity object for the view entity
1023
- this._viewEntity = params.ViewEntity;
1024
- const e = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.EntityID); });
1025
- if (e)
1026
- this._entityInfo = e;
1027
- else
1028
- throw new Error("Unable to get entity info for view: " + ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Name));
1011
+ else if (!params.ViewEntity && (params.ViewID || params.ViewName)) {
1012
+ // this is NOT a dyamic view as we got either the ViewID or ViewName, so we can get the ViewEntity
1013
+ if (params.ViewID && params.ViewID.length > 0) {
1014
+ this._viewEntity = await ViewInfo.GetViewEntity(params.ViewID);
1029
1015
  }
1030
- else if (!params.ViewEntity && (params.ViewID || params.ViewName)) {
1031
- // this is NOT a dyamic view as we got either the ViewID or ViewName, so we can get the ViewEntity
1032
- if (params.ViewID && params.ViewID.length > 0) {
1033
- this._viewEntity = (yield ViewInfo.GetViewEntity(params.ViewID));
1034
- }
1035
- else if (params.ViewName) {
1036
- this._viewEntity = (yield ViewInfo.GetViewEntityByName(params.ViewName));
1037
- }
1038
- params.ViewEntity = this._viewEntity;
1039
- const e = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.EntityID); });
1040
- if (e)
1041
- this._entityInfo = e;
1042
- else
1043
- throw new Error("Unable to get entity info for view: " + ((_b = this._viewEntity) === null || _b === void 0 ? void 0 : _b.Name));
1044
- }
1045
- else if (params.EntityName) {
1046
- // we don't have a ViewEntity because we're doing a dynamic view, so we need to get the entity info from the Entity Name
1047
- const e = md.Entities.find(x => x.Name === params.EntityName);
1048
- if (e)
1049
- this._entityInfo = e;
1016
+ else if (params.ViewName) {
1017
+ this._viewEntity = await ViewInfo.GetViewEntityByName(params.ViewName);
1050
1018
  }
1019
+ params.ViewEntity = this._viewEntity;
1020
+ const e = md.Entities.find(x => x.ID === this._viewEntity?.EntityID);
1021
+ if (e)
1022
+ this._entityInfo = e;
1051
1023
  else
1052
- throw new Error("Invalid configuration, we need to receive either a ViewEntity, ViewID, ViewName, or EntityName and ExtraFilter in order to run a view");
1053
- const rvResult = yield rv.RunView(params);
1054
- if (!rvResult.Success) {
1055
- // it failed
1056
- this.CreateSimpleNotification("Error running view:\n\n" + rvResult.ErrorMessage, 'error', 5000);
1057
- }
1058
- else {
1059
- // it worked
1060
- this.viewData = rvResult.Results;
1061
- this.totalRowCount = rvResult.TotalRowCount;
1062
- this.formattedData = new Array(this.viewData.length);
1063
- let cols;
1064
- if (this._viewEntity)
1065
- cols = this._viewEntity.Columns;
1066
- else
1067
- cols = (_c = this._entityInfo) === null || _c === void 0 ? void 0 : _c.Fields.filter((f) => f.DefaultInView).map((f) => {
1068
- return {
1069
- ID: f.ID,
1070
- Name: f.CodeName,
1071
- DisplayName: f.DisplayName,
1072
- EntityField: f,
1073
- hidden: false,
1074
- orderIndex: f.Sequence,
1075
- width: f.DefaultColumnWidth ? f.DefaultColumnWidth : 100,
1076
- };
1077
- });
1078
- if (cols) {
1079
- this.viewColumns = cols;
1080
- const tempCols = cols.filter(x => x.hidden === false && x.EntityField /*make sure there is an entity field linked*/).sort((a, b) => {
1081
- const aOrder = a.orderIndex != null ? a.orderIndex : 9999;
1082
- const bOrder = b.orderIndex != null ? b.orderIndex : 9999;
1083
- return aOrder - bOrder;
1084
- });
1085
- this.visibleColumns = tempCols;
1086
- }
1087
- // sorting setup
1088
- if (this._viewEntity) {
1089
- const temp = this._viewEntity.ViewSortInfo;
1090
- const kendoSortSettings = temp.map((s) => {
1091
- let dir;
1092
- if (typeof s.direction === 'string')
1093
- dir = s.direction.trim().toLowerCase();
1094
- else if (typeof s.direction === 'number' && s.direction === 1)
1095
- dir = 'asc';
1096
- else if (typeof s.direction === 'number' && s.direction === 2)
1097
- dir = 'desc';
1098
- else
1099
- dir = '';
1100
- return { field: s.field, dir: dir };
1101
- });
1102
- this.sortSettings = kendoSortSettings;
1103
- }
1104
- this.skip = 0;
1105
- this.virtualLoadData();
1106
- this.LoadEntityActions();
1107
- }
1108
- this.viewExecutionTime = (new Date().getTime() - startTime) / 1000; // in seconds
1109
- this.isLoading = false;
1024
+ throw new Error("Unable to get entity info for view: " + this._viewEntity?.Name);
1025
+ }
1026
+ else if (params.EntityName) {
1027
+ // we don't have a ViewEntity because we're doing a dynamic view, so we need to get the entity info from the Entity Name
1028
+ const e = md.Entities.find(x => x.Name === params.EntityName);
1029
+ if (e)
1030
+ this._entityInfo = e;
1031
+ }
1032
+ else
1033
+ throw new Error("Invalid configuration, we need to receive either a ViewEntity, ViewID, ViewName, or EntityName and ExtraFilter in order to run a view");
1034
+ const rvResult = await rv.RunView(params);
1035
+ if (!rvResult.Success) {
1036
+ // it failed
1037
+ this.CreateSimpleNotification("Error running view:\n\n" + rvResult.ErrorMessage, 'error', 5000);
1110
1038
  }
1111
1039
  else {
1112
- LogError("Refresh(params) must have ViewID or ViewName or (EntityName and ExtraFilter)");
1040
+ // it worked
1041
+ this.viewData = rvResult.Results;
1042
+ this.totalRowCount = rvResult.TotalRowCount;
1043
+ this.formattedData = new Array(this.viewData.length);
1044
+ let cols;
1045
+ if (this._viewEntity)
1046
+ cols = this._viewEntity.Columns;
1047
+ else
1048
+ cols = this._entityInfo?.Fields.filter((f) => f.DefaultInView).map((f) => {
1049
+ return {
1050
+ ID: f.ID,
1051
+ Name: f.CodeName,
1052
+ DisplayName: f.DisplayName,
1053
+ EntityField: f,
1054
+ hidden: false,
1055
+ orderIndex: f.Sequence,
1056
+ width: f.DefaultColumnWidth ? f.DefaultColumnWidth : 100,
1057
+ };
1058
+ });
1059
+ if (cols) {
1060
+ this.viewColumns = cols;
1061
+ const tempCols = cols.filter(x => x.hidden === false && x.EntityField /*make sure there is an entity field linked*/).sort((a, b) => {
1062
+ const aOrder = a.orderIndex != null ? a.orderIndex : 9999;
1063
+ const bOrder = b.orderIndex != null ? b.orderIndex : 9999;
1064
+ return aOrder - bOrder;
1065
+ });
1066
+ this.visibleColumns = tempCols;
1067
+ }
1068
+ // sorting setup
1069
+ if (this._viewEntity) {
1070
+ const temp = this._viewEntity.ViewSortInfo;
1071
+ const kendoSortSettings = temp.map((s) => {
1072
+ let dir;
1073
+ if (typeof s.direction === 'string')
1074
+ dir = s.direction.trim().toLowerCase();
1075
+ else if (typeof s.direction === 'number' && s.direction === 1)
1076
+ dir = 'asc';
1077
+ else if (typeof s.direction === 'number' && s.direction === 2)
1078
+ dir = 'desc';
1079
+ else
1080
+ dir = '';
1081
+ return { field: s.field, dir: dir };
1082
+ });
1083
+ this.sortSettings = kendoSortSettings;
1084
+ }
1085
+ this.skip = 0;
1086
+ this.virtualLoadData();
1087
+ this.LoadEntityActions();
1113
1088
  }
1114
- });
1089
+ this.viewExecutionTime = (new Date().getTime() - startTime) / 1000; // in seconds
1090
+ this.isLoading = false;
1091
+ }
1092
+ else {
1093
+ LogError("Refresh(params) must have ViewID or ViewName or (EntityName and ExtraFilter)");
1094
+ }
1115
1095
  }
1116
1096
  /**
1117
1097
  * Load up the entity action metadata for the current entity the view is displaying
@@ -1122,17 +1102,15 @@ export class UserViewGridComponent {
1122
1102
  }
1123
1103
  }
1124
1104
  GetColumnTitle(col) {
1125
- var _a;
1126
1105
  if (col.DisplayName)
1127
1106
  return col.DisplayName; // use view's display name first if it exists
1128
- else if ((_a = col.EntityField) === null || _a === void 0 ? void 0 : _a.DisplayName)
1107
+ else if (col.EntityField?.DisplayName)
1129
1108
  return col.EntityField.DisplayName; // then use entity display name, if that exist
1130
1109
  else
1131
1110
  return col.Name; // otherwise just use the column name
1132
1111
  }
1133
1112
  GetColumnCellStyle(col) {
1134
- var _a;
1135
- switch ((_a = col.EntityField) === null || _a === void 0 ? void 0 : _a.Type.trim().toLowerCase()) {
1113
+ switch (col.EntityField?.Type.trim().toLowerCase()) {
1136
1114
  case "money":
1137
1115
  case 'decimal':
1138
1116
  case 'real':
@@ -1206,240 +1184,233 @@ export class UserViewGridComponent {
1206
1184
  }
1207
1185
  }
1208
1186
  }
1209
- closeConfirmMergeDialog(event) {
1210
- return __awaiter(this, void 0, void 0, function* () {
1211
- if (event === 'yes') {
1212
- if (this._entityInfo && this.recordCompareComponent) {
1213
- const md = new Metadata();
1214
- const pkeys = this._entityInfo.PrimaryKeys;
1215
- const result = yield md.MergeRecords({
1216
- EntityName: this._entityInfo.Name,
1217
- RecordsToMerge: this.recordsToCompare.map((r) => {
1218
- return r.PrimaryKey;
1219
- }).filter((compositeKey) => {
1220
- if (!this.recordCompareComponent) {
1221
- return false;
1222
- }
1223
- return this.recordCompareComponent.selectedRecordCompositeKey.Equals(compositeKey);
1224
- }),
1225
- SurvivingRecordCompositeKey: this.recordCompareComponent.selectedRecordCompositeKey,
1226
- FieldMap: this.recordCompareComponent.fieldMap.map((fm) => {
1227
- return {
1228
- FieldName: fm.fieldName,
1229
- Value: fm.value
1230
- };
1231
- })
1232
- });
1233
- if (result.Success) {
1234
- // merge was successful, so refresh the grid
1235
- this.selectedKeys = [];
1236
- this.recordsToCompare = [];
1237
- this.mergeMode = false;
1238
- this.compareMode = false;
1239
- // close the dialogs
1240
- this.isCompareDialogOpened = false;
1241
- this.isConfirmDialogOpen = false;
1242
- // refresh the grid
1243
- this.Refresh(this.Params);
1244
- }
1245
- else {
1246
- // the merge failed, so show an error message
1247
- this.isConfirmDialogOpen = false;
1248
- this.CreateSimpleNotification("Error merging records: " + result.OverallStatus, 'error', 5000);
1249
- }
1250
- }
1251
- }
1252
- else {
1253
- this.isConfirmDialogOpen = false;
1254
- // close the dialog and let the user continue to work on the merge, so don't close the compare dialog
1255
- }
1256
- });
1257
- }
1258
- closeCompareDialog(event) {
1259
- return __awaiter(this, void 0, void 0, function* () {
1260
- switch (event) {
1261
- case 'merge':
1262
- // user has requested to merge the records and retain the selected record from the compare records component, so run the merge
1263
- // first, confirm with the user to make 100% sure they want to do this as it is irreversible
1264
- this.isConfirmDialogOpen = true;
1265
- break;
1266
- default: // close and cancel
1187
+ async closeConfirmMergeDialog(event) {
1188
+ if (event === 'yes') {
1189
+ if (this._entityInfo && this.recordCompareComponent) {
1190
+ const md = new Metadata();
1191
+ const pkeys = this._entityInfo.PrimaryKeys;
1192
+ const result = await md.MergeRecords({
1193
+ EntityName: this._entityInfo.Name,
1194
+ RecordsToMerge: this.recordsToCompare.map((r) => {
1195
+ return r.PrimaryKey;
1196
+ }).filter((compositeKey) => {
1197
+ if (!this.recordCompareComponent) {
1198
+ return false;
1199
+ }
1200
+ return this.recordCompareComponent.selectedRecordCompositeKey.Equals(compositeKey);
1201
+ }),
1202
+ SurvivingRecordCompositeKey: this.recordCompareComponent.selectedRecordCompositeKey,
1203
+ FieldMap: this.recordCompareComponent.fieldMap.map((fm) => {
1204
+ return {
1205
+ FieldName: fm.fieldName,
1206
+ Value: fm.value
1207
+ };
1208
+ })
1209
+ });
1210
+ if (result.Success) {
1211
+ // merge was successful, so refresh the grid
1267
1212
  this.selectedKeys = [];
1268
1213
  this.recordsToCompare = [];
1269
1214
  this.mergeMode = false;
1270
1215
  this.compareMode = false;
1271
- this.duplicateMode = false;
1272
- this.addToListMode = false;
1216
+ // close the dialogs
1273
1217
  this.isCompareDialogOpened = false;
1274
- break;
1218
+ this.isConfirmDialogOpen = false;
1219
+ // refresh the grid
1220
+ this.Refresh(this.Params);
1221
+ }
1222
+ else {
1223
+ // the merge failed, so show an error message
1224
+ this.isConfirmDialogOpen = false;
1225
+ this.CreateSimpleNotification("Error merging records: " + result.OverallStatus, 'error', 5000);
1226
+ }
1275
1227
  }
1276
- });
1228
+ }
1229
+ else {
1230
+ this.isConfirmDialogOpen = false;
1231
+ // close the dialog and let the user continue to work on the merge, so don't close the compare dialog
1232
+ }
1277
1233
  }
1278
- findDuplicateRecords() {
1279
- return __awaiter(this, void 0, void 0, function* () {
1280
- var _a;
1281
- if (!this._entityInfo) {
1282
- console.error("Entity Info is not available");
1283
- this.closeCompareDialog('duplicate');
1284
- return;
1285
- }
1286
- const md = new Metadata();
1287
- const list = yield md.GetEntityObject('Lists');
1288
- list.NewRecord();
1289
- list.Name = `Potential Duplicate Run`;
1290
- list.Description = `Potential Duplicate Run for ${this._entityInfo.Name} Entity`;
1291
- list.EntityID = this._entityInfo.ID;
1292
- list.UserID = md.CurrentUser.ID;
1293
- const saveResult = yield list.Save();
1294
- if (!saveResult) {
1295
- LogError(`Failed to save list for Potential Duplicate Run`, undefined, list.LatestResult);
1234
+ async closeCompareDialog(event) {
1235
+ switch (event) {
1236
+ case 'merge':
1237
+ // user has requested to merge the records and retain the selected record from the compare records component, so run the merge
1238
+ // first, confirm with the user to make 100% sure they want to do this as it is irreversible
1239
+ this.isConfirmDialogOpen = true;
1240
+ break;
1241
+ default: // close and cancel
1242
+ this.selectedKeys = [];
1243
+ this.recordsToCompare = [];
1244
+ this.mergeMode = false;
1245
+ this.compareMode = false;
1246
+ this.duplicateMode = false;
1247
+ this.addToListMode = false;
1248
+ this.isCompareDialogOpened = false;
1249
+ break;
1250
+ }
1251
+ }
1252
+ async findDuplicateRecords() {
1253
+ if (!this._entityInfo) {
1254
+ console.error("Entity Info is not available");
1255
+ this.closeCompareDialog('duplicate');
1256
+ return;
1257
+ }
1258
+ const md = new Metadata();
1259
+ const list = await md.GetEntityObject('Lists');
1260
+ list.NewRecord();
1261
+ list.Name = `Potential Duplicate Run`;
1262
+ list.Description = `Potential Duplicate Run for ${this._entityInfo.Name} Entity`;
1263
+ list.EntityID = this._entityInfo.ID;
1264
+ list.UserID = md.CurrentUser.ID;
1265
+ const saveResult = await list.Save();
1266
+ if (!saveResult) {
1267
+ LogError(`Failed to save list for Potential Duplicate Run`, undefined, list.LatestResult);
1268
+ return;
1269
+ }
1270
+ let params = new PotentialDuplicateRequest();
1271
+ params.EntityID = this._entityInfo?.ID;
1272
+ params.ListID = list.ID;
1273
+ params.RecordIDs = [];
1274
+ for (const index of this.selectedKeys) {
1275
+ const viewData = this.viewData[index];
1276
+ const idField = viewData.ID;
1277
+ const listDetail = await md.GetEntityObject('List Details');
1278
+ listDetail.NewRecord();
1279
+ listDetail.ListID = list.ID;
1280
+ listDetail.RecordID = idField.toString();
1281
+ listDetail.ContextCurrentUser = md.CurrentUser;
1282
+ const ldSaveResult = await listDetail.Save();
1283
+ if (!ldSaveResult) {
1284
+ LogError(`Failed to save list detail for Potential Duplicate Run`, undefined, listDetail.LatestResult);
1296
1285
  return;
1297
1286
  }
1298
- let params = new PotentialDuplicateRequest();
1299
- params.EntityID = (_a = this._entityInfo) === null || _a === void 0 ? void 0 : _a.ID;
1300
- params.ListID = list.ID;
1301
- params.RecordIDs = [];
1302
- for (const index of this.selectedKeys) {
1303
- const viewData = this.viewData[index];
1304
- const idField = viewData.ID;
1305
- const listDetail = yield md.GetEntityObject('List Details');
1306
- listDetail.NewRecord();
1307
- listDetail.ListID = list.ID;
1308
- listDetail.RecordID = idField.toString();
1309
- listDetail.ContextCurrentUser = md.CurrentUser;
1310
- const ldSaveResult = yield listDetail.Save();
1311
- if (!ldSaveResult) {
1312
- LogError(`Failed to save list detail for Potential Duplicate Run`, undefined, listDetail.LatestResult);
1313
- return;
1314
- }
1315
- }
1316
- this.closeCompareDialog('duplicate');
1317
- this.CreateSimpleNotification("Working on finding duplicates, will notify you when it is complete...", 'info', 2000);
1318
- let response = yield md.GetRecordDuplicates(params, md.CurrentUser);
1319
- console.log(response);
1320
- });
1287
+ }
1288
+ this.closeCompareDialog('duplicate');
1289
+ this.CreateSimpleNotification("Working on finding duplicates, will notify you when it is complete...", 'info', 2000);
1290
+ let response = await md.GetRecordDuplicates(params, md.CurrentUser);
1291
+ console.log(response);
1321
1292
  }
1322
- doExcelExport() {
1323
- return __awaiter(this, void 0, void 0, function* () {
1324
- if (this.kendoExcelExport === null)
1325
- throw new Error("kendoExcelExport is null, cannot export data");
1326
- try {
1327
- this.CreateSimpleNotification("Working on the export, will notify you when it is complete...", 'info', 2000);
1328
- const data = yield this.getExportData();
1329
- // we have the data.
1330
- const cols = this.viewColumns.filter((vc) => vc.hidden === false);
1331
- this.exportColumns = cols;
1332
- this.exportData = data;
1333
- // before we call the save, we need to let Angular do its thing that will result in the kendoExcelExport component binding properly to
1334
- // the exportColumns and exportData arrays. So we wait for the next tick before we call save()
1335
- setTimeout(() => {
1336
- this.kendoExcelExport.save();
1337
- this.CreateSimpleNotification("Excel Export Complete", 'success', 2000);
1338
- }, 100);
1339
- }
1340
- catch (e) {
1341
- this.CreateSimpleNotification("Error exporting data", 'error', 5000);
1342
- LogError(e);
1343
- }
1344
- });
1293
+ // Export Functionality
1294
+ exportColumns = [];
1295
+ exportData = [];
1296
+ async doExcelExport() {
1297
+ if (this.kendoExcelExport === null)
1298
+ throw new Error("kendoExcelExport is null, cannot export data");
1299
+ try {
1300
+ this.CreateSimpleNotification("Working on the export, will notify you when it is complete...", 'info', 2000);
1301
+ const data = await this.getExportData();
1302
+ // we have the data.
1303
+ const cols = this.viewColumns.filter((vc) => vc.hidden === false);
1304
+ this.exportColumns = cols;
1305
+ this.exportData = data;
1306
+ // before we call the save, we need to let Angular do its thing that will result in the kendoExcelExport component binding properly to
1307
+ // the exportColumns and exportData arrays. So we wait for the next tick before we call save()
1308
+ setTimeout(() => {
1309
+ this.kendoExcelExport.save();
1310
+ this.CreateSimpleNotification("Excel Export Complete", 'success', 2000);
1311
+ }, 100);
1312
+ }
1313
+ catch (e) {
1314
+ this.CreateSimpleNotification("Error exporting data", 'error', 5000);
1315
+ LogError(e);
1316
+ }
1345
1317
  }
1346
- getExportData() {
1347
- return __awaiter(this, void 0, void 0, function* () {
1348
- // Get the data for the ENTIRE view, not just the current page
1349
- const md = new Metadata();
1350
- const rv = new RunView();
1351
- const p = Object.assign(Object.assign({}, this.Params), { IgnoreMaxRows: true, ForceAuditLog: true, AuditLogDescription: `Export of Data From ${this._viewEntity ? '"' + this._viewEntity.Get('Name') + '"' : ''} View for User ${md.CurrentUser.Email}` });
1352
- const result = yield rv.RunView(p);
1353
- if (result && result.Success) {
1354
- return result.Results;
1355
- }
1356
- else
1357
- throw new Error("Unable to get export data");
1358
- });
1318
+ async getExportData() {
1319
+ // Get the data for the ENTIRE view, not just the current page
1320
+ const md = new Metadata();
1321
+ const rv = new RunView();
1322
+ const p = {
1323
+ ...this.Params,
1324
+ IgnoreMaxRows: true,
1325
+ ForceAuditLog: true,
1326
+ AuditLogDescription: `Export of Data From ${this._viewEntity ? '"' + this._viewEntity.Get('Name') + '"' : ''} View for User ${md.CurrentUser.Email}`
1327
+ };
1328
+ const result = await rv.RunView(p);
1329
+ if (result && result.Success) {
1330
+ return result.Results;
1331
+ }
1332
+ else
1333
+ throw new Error("Unable to get export data");
1359
1334
  }
1335
+ showTemplatePreviewDialog = false;
1360
1336
  /**
1361
1337
  * Handles communication functionality for a given view, only available if the entity being displayed supports communication.
1362
1338
  */
1363
- doCommunication() {
1364
- return __awaiter(this, void 0, void 0, function* () {
1365
- if (!this.Params)
1366
- return;
1367
- this.showTemplatePreviewDialog = true;
1368
- });
1339
+ async doCommunication() {
1340
+ if (!this.Params)
1341
+ return;
1342
+ this.showTemplatePreviewDialog = true;
1369
1343
  }
1370
1344
  /**
1371
1345
  * This method will invoke the selected action
1372
1346
  * @param action
1373
1347
  */
1374
- doEntityAction(action) {
1375
- return __awaiter(this, void 0, void 0, function* () {
1376
- var _a;
1377
- try {
1378
- // Get the currently selected record if we have one
1379
- if (!this._entityInfo) {
1380
- SharedService.Instance.CreateSimpleNotification("Unable to determine entity information", "error", 3000);
1381
- return;
1382
- }
1383
- // Check if we have selected rows
1384
- const selectedItems = ((_a = this.selectedKeys) === null || _a === void 0 ? void 0 : _a.length) > 0
1385
- ? this.selectedKeys.map(key => this.viewData[key])
1386
- : null;
1387
- // Get reference to data provider and create ActionClient
1388
- const md = new Metadata();
1389
- // Since we can't access provider directly with typing, use a temporary any cast
1390
- const provider = md._provider;
1391
- const actionClient = new GraphQLActionClient(provider);
1392
- // Determine the invocation type based on selection
1393
- let invocationType = 'View'; // Default to View invocation type
1394
- let entityObject = null;
1395
- let result = null;
1396
- // If we have selected records, use SingleRecord type for the first selected record
1397
- if (selectedItems && selectedItems.length > 0) {
1398
- invocationType = 'SingleRecord';
1399
- // Get the entity object for the first selected record
1400
- const compositeKey = new CompositeKey();
1401
- compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, selectedItems[0]);
1402
- entityObject = yield md.GetEntityObject(this._entityInfo.Name);
1403
- yield entityObject.InnerLoad(compositeKey);
1404
- }
1405
- // Run the entity action
1406
- if (invocationType === 'SingleRecord' && entityObject) {
1407
- const params = {
1408
- EntityAction: action,
1409
- InvocationType: { Name: invocationType },
1410
- EntityObject: entityObject,
1411
- ContextUser: md.CurrentUser
1412
- };
1413
- result = yield actionClient.RunEntityAction(params);
1414
- }
1415
- else if (invocationType === 'View') {
1416
- const params = {
1417
- EntityAction: action,
1418
- InvocationType: { Name: invocationType },
1419
- ViewID: this.ViewID,
1420
- ContextUser: md.CurrentUser
1421
- };
1422
- result = yield actionClient.RunEntityAction(params);
1423
- }
1424
- if (result) {
1425
- if (result.Success) {
1426
- SharedService.Instance.CreateSimpleNotification(`Action ${action.Action} executed successfully`, "success", 3000);
1427
- // Refresh the grid if needed
1428
- if (this.Params) {
1429
- this.Refresh(this.Params);
1430
- }
1431
- }
1432
- else {
1433
- SharedService.Instance.CreateSimpleNotification(`Error executing action: ${result.Message}`, "error", 5000);
1348
+ async doEntityAction(action) {
1349
+ try {
1350
+ // Get the currently selected record if we have one
1351
+ if (!this._entityInfo) {
1352
+ SharedService.Instance.CreateSimpleNotification("Unable to determine entity information", "error", 3000);
1353
+ return;
1354
+ }
1355
+ // Check if we have selected rows
1356
+ const selectedItems = this.selectedKeys?.length > 0
1357
+ ? this.selectedKeys.map(key => this.viewData[key])
1358
+ : null;
1359
+ // Get reference to data provider and create ActionClient
1360
+ const md = new Metadata();
1361
+ // Since we can't access provider directly with typing, use a temporary any cast
1362
+ const provider = md._provider;
1363
+ const actionClient = new GraphQLActionClient(provider);
1364
+ // Determine the invocation type based on selection
1365
+ let invocationType = 'View'; // Default to View invocation type
1366
+ let entityObject = null;
1367
+ let result = null;
1368
+ // If we have selected records, use SingleRecord type for the first selected record
1369
+ if (selectedItems && selectedItems.length > 0) {
1370
+ invocationType = 'SingleRecord';
1371
+ // Get the entity object for the first selected record
1372
+ const compositeKey = new CompositeKey();
1373
+ compositeKey.LoadFromEntityInfoAndRecord(this._entityInfo, selectedItems[0]);
1374
+ entityObject = await md.GetEntityObject(this._entityInfo.Name);
1375
+ await entityObject.InnerLoad(compositeKey);
1376
+ }
1377
+ // Run the entity action
1378
+ if (invocationType === 'SingleRecord' && entityObject) {
1379
+ const params = {
1380
+ EntityAction: action,
1381
+ InvocationType: { Name: invocationType },
1382
+ EntityObject: entityObject,
1383
+ ContextUser: md.CurrentUser
1384
+ };
1385
+ result = await actionClient.RunEntityAction(params);
1386
+ }
1387
+ else if (invocationType === 'View') {
1388
+ const params = {
1389
+ EntityAction: action,
1390
+ InvocationType: { Name: invocationType },
1391
+ ViewID: this.ViewID,
1392
+ ContextUser: md.CurrentUser
1393
+ };
1394
+ result = await actionClient.RunEntityAction(params);
1395
+ }
1396
+ if (result) {
1397
+ if (result.Success) {
1398
+ SharedService.Instance.CreateSimpleNotification(`Action ${action.Action} executed successfully`, "success", 3000);
1399
+ // Refresh the grid if needed
1400
+ if (this.Params) {
1401
+ this.Refresh(this.Params);
1434
1402
  }
1435
1403
  }
1404
+ else {
1405
+ SharedService.Instance.CreateSimpleNotification(`Error executing action: ${result.Message}`, "error", 5000);
1406
+ }
1436
1407
  }
1437
- catch (e) {
1438
- const error = e;
1439
- LogError(`Error invoking entity action: ${error}`);
1440
- SharedService.Instance.CreateSimpleNotification(`Error invoking action: ${error.message}`, "error", 5000);
1441
- }
1442
- });
1408
+ }
1409
+ catch (e) {
1410
+ const error = e;
1411
+ LogError(`Error invoking entity action: ${error}`);
1412
+ SharedService.Instance.CreateSimpleNotification(`Error invoking action: ${error.message}`, "error", 5000);
1413
+ }
1443
1414
  }
1444
1415
  get EntitySupportsCommunication() {
1445
1416
  try {
@@ -1452,130 +1423,118 @@ export class UserViewGridComponent {
1452
1423
  return false; // make this non fatal - this can occur at times due to timing issues, it seems, we need to investigate further
1453
1424
  }
1454
1425
  }
1426
+ entityFormDialog = null;
1455
1427
  /**
1456
1428
  * This method will create a new record of the given entity type. It will only work if the User has the ability to create records of
1457
1429
  * this entity type and also if the entity level setting AllowCreateAPI is set to 1. If either of these conditions are not met, then
1458
1430
  * this method will do nothing.
1459
1431
  */
1460
- doCreateNewRecord() {
1461
- return __awaiter(this, void 0, void 0, function* () {
1462
- var _a;
1463
- // creates a new record either using a dialog or with the router
1464
- if (this.UserCanCreateNewRecord && this._entityInfo) {
1465
- if (this.CreateRecordMode === 'Tab') {
1466
- // route to a resource/record with a blank string for the 3rd segment which is normally the pkey value
1467
- // here we don't provide the pkey value so the record component will know to create a new record
1468
- this.router.navigate(['resource', 'record', '' /*add this 3rd param that's blank so the route validates*/], { queryParams: {
1469
- Entity: this._entityInfo.Name,
1470
- NewRecordValues: this.NewRecordValues ? (_a = FieldValueCollection.FromObject(this.NewRecordValues)) === null || _a === void 0 ? void 0 : _a.ToURLSegment() : null
1471
- }
1472
- });
1473
- }
1474
- else {
1475
- // configured to display a dialog instead, we'll use the entity-form-dialog for this
1476
- if (this.entityFormDialog) {
1477
- const md = new Metadata();
1478
- const newRecord = yield md.GetEntityObject(this._entityInfo.Name);
1479
- if (this.NewRecordValues) {
1480
- // we have new record values in a simple JS object, so grab the key/values from the object and set the values in the new record for non null/undefined values
1481
- Object.keys(this.NewRecordValues).filter((key) => this.NewRecordValues[key] !== null && this.NewRecordValues[key] !== undefined).forEach((key) => {
1482
- newRecord.Set(key, this.NewRecordValues[key]);
1483
- });
1484
- }
1485
- this.entityFormDialog.Record = newRecord;
1486
- this.showNewRecordDialog = true;
1487
- }
1488
- else {
1489
- // don't have the dialog reference, throw an error
1490
- throw new Error("Unable to create new record, entity-form-dialog is not available");
1432
+ async doCreateNewRecord() {
1433
+ // creates a new record either using a dialog or with the router
1434
+ if (this.UserCanCreateNewRecord && this._entityInfo) {
1435
+ if (this.CreateRecordMode === 'Tab') {
1436
+ // route to a resource/record with a blank string for the 3rd segment which is normally the pkey value
1437
+ // here we don't provide the pkey value so the record component will know to create a new record
1438
+ this.router.navigate(['resource', 'record', '' /*add this 3rd param that's blank so the route validates*/], { queryParams: {
1439
+ Entity: this._entityInfo.Name,
1440
+ NewRecordValues: this.NewRecordValues ? FieldValueCollection.FromObject(this.NewRecordValues)?.ToURLSegment() : null
1491
1441
  }
1492
- }
1442
+ });
1493
1443
  }
1494
- });
1495
- }
1496
- toggleAddToListDialog(show) {
1497
- return __awaiter(this, void 0, void 0, function* () {
1498
- this.showAddToListDialog = show;
1499
- if (show) {
1500
- if (!this.sourceListEntities) {
1501
- yield this.loadListEntities();
1444
+ else {
1445
+ // configured to display a dialog instead, we'll use the entity-form-dialog for this
1446
+ if (this.entityFormDialog) {
1447
+ const md = new Metadata();
1448
+ const newRecord = await md.GetEntityObject(this._entityInfo.Name);
1449
+ if (this.NewRecordValues) {
1450
+ // we have new record values in a simple JS object, so grab the key/values from the object and set the values in the new record for non null/undefined values
1451
+ Object.keys(this.NewRecordValues).filter((key) => this.NewRecordValues[key] !== null && this.NewRecordValues[key] !== undefined).forEach((key) => {
1452
+ newRecord.Set(key, this.NewRecordValues[key]);
1453
+ });
1454
+ }
1455
+ this.entityFormDialog.Record = newRecord;
1456
+ this.showNewRecordDialog = true;
1502
1457
  }
1503
1458
  else {
1504
- this.listEntities = this.sourceListEntities;
1505
- this.selectedListEntities = [];
1459
+ // don't have the dialog reference, throw an error
1460
+ throw new Error("Unable to create new record, entity-form-dialog is not available");
1506
1461
  }
1507
1462
  }
1508
- else {
1509
- this.enableCheckbox(true, 'addToList');
1510
- }
1511
- this.setupSearchDebounce();
1512
- });
1463
+ }
1513
1464
  }
1514
- loadListEntities() {
1515
- return __awaiter(this, void 0, void 0, function* () {
1516
- if (!this._entityInfo) {
1517
- LogError("Entity Info is not set");
1518
- return;
1465
+ async toggleAddToListDialog(show) {
1466
+ this.showAddToListDialog = show;
1467
+ if (show) {
1468
+ if (!this.sourceListEntities) {
1469
+ await this.loadListEntities();
1519
1470
  }
1520
- const md = new Metadata();
1521
- const rv = new RunView();
1522
- const rvResult = yield rv.RunView({
1523
- EntityName: 'Lists',
1524
- ExtraFilter: `UserID = '${md.CurrentUser.ID}' AND EntityID = '${this._entityInfo.ID}'`,
1525
- ResultType: 'entity_object'
1526
- });
1527
- if (!rvResult.Success) {
1528
- LogError("Failed to load List Entities");
1529
- return;
1471
+ else {
1472
+ this.listEntities = this.sourceListEntities;
1473
+ this.selectedListEntities = [];
1530
1474
  }
1531
- this.sourceListEntities = this.listEntities = rvResult.Results;
1532
- });
1475
+ }
1476
+ else {
1477
+ this.enableCheckbox(true, 'addToList');
1478
+ }
1479
+ this.setupSearchDebounce();
1533
1480
  }
1534
- addToList(listEntity) {
1535
- return __awaiter(this, void 0, void 0, function* () {
1536
- console.log('add to list', listEntity.Name);
1537
- this.selectedListEntities.push(listEntity);
1538
- this.selectedListEntities.includes(listEntity);
1481
+ async loadListEntities() {
1482
+ if (!this._entityInfo) {
1483
+ LogError("Entity Info is not set");
1484
+ return;
1485
+ }
1486
+ const md = new Metadata();
1487
+ const rv = new RunView();
1488
+ const rvResult = await rv.RunView({
1489
+ EntityName: 'Lists',
1490
+ ExtraFilter: `UserID = '${md.CurrentUser.ID}' AND EntityID = '${this._entityInfo.ID}'`,
1491
+ ResultType: 'entity_object'
1539
1492
  });
1493
+ if (!rvResult.Success) {
1494
+ LogError("Failed to load List Entities");
1495
+ return;
1496
+ }
1497
+ this.sourceListEntities = this.listEntities = rvResult.Results;
1540
1498
  }
1541
- removeFromList(listEntity) {
1542
- return __awaiter(this, void 0, void 0, function* () {
1543
- console.log('remove from list', listEntity.Name);
1544
- this.selectedListEntities = this.selectedListEntities.filter((le) => le.ID !== listEntity.ID);
1545
- });
1499
+ async addToList(listEntity) {
1500
+ console.log('add to list', listEntity.Name);
1501
+ this.selectedListEntities.push(listEntity);
1502
+ this.selectedListEntities.includes(listEntity);
1546
1503
  }
1547
- addRecordsToSelectedLists() {
1548
- return __awaiter(this, void 0, void 0, function* () {
1549
- this.showAddToListLoader = true;
1550
- const md = new Metadata();
1551
- let errorCount = 0;
1552
- for (const listEntity of this.selectedListEntities) {
1553
- for (const index of this.selectedKeys) {
1554
- const listDetail = yield md.GetEntityObject('List Details');
1555
- const viewData = this.viewData[index];
1556
- const idField = viewData.ID;
1557
- listDetail.NewRecord();
1558
- listDetail.ListID = listEntity.ID;
1559
- listDetail.RecordID = idField.toString();
1560
- listDetail.Sequence = 0;
1561
- listDetail.ContextCurrentUser = md.CurrentUser;
1562
- let saveResult = yield listDetail.Save();
1563
- if (!saveResult) {
1564
- LogError(`Failed to save record to list: ${listEntity.Name}`);
1565
- LogError(listDetail.LatestResult);
1566
- errorCount++;
1567
- }
1504
+ async removeFromList(listEntity) {
1505
+ console.log('remove from list', listEntity.Name);
1506
+ this.selectedListEntities = this.selectedListEntities.filter((le) => le.ID !== listEntity.ID);
1507
+ }
1508
+ async addRecordsToSelectedLists() {
1509
+ this.showAddToListLoader = true;
1510
+ const md = new Metadata();
1511
+ let errorCount = 0;
1512
+ for (const listEntity of this.selectedListEntities) {
1513
+ for (const index of this.selectedKeys) {
1514
+ const listDetail = await md.GetEntityObject('List Details');
1515
+ const viewData = this.viewData[index];
1516
+ const idField = viewData.ID;
1517
+ listDetail.NewRecord();
1518
+ listDetail.ListID = listEntity.ID;
1519
+ listDetail.RecordID = idField.toString();
1520
+ listDetail.Sequence = 0;
1521
+ listDetail.ContextCurrentUser = md.CurrentUser;
1522
+ let saveResult = await listDetail.Save();
1523
+ if (!saveResult) {
1524
+ LogError(`Failed to save record to list: ${listEntity.Name}`);
1525
+ LogError(listDetail.LatestResult);
1526
+ errorCount++;
1568
1527
  }
1569
1528
  }
1570
- if (errorCount === 0) {
1571
- this.CreateSimpleNotification('Records successfully added to the selected lists', 'success', 2000);
1572
- }
1573
- else {
1574
- this.CreateSimpleNotification('Some records failed to be added to the selected lists', 'error', 2000);
1575
- }
1576
- this.showAddToListLoader = false;
1577
- this.toggleAddToListDialog(false);
1578
- });
1529
+ }
1530
+ if (errorCount === 0) {
1531
+ this.CreateSimpleNotification('Records successfully added to the selected lists', 'success', 2000);
1532
+ }
1533
+ else {
1534
+ this.CreateSimpleNotification('Some records failed to be added to the selected lists', 'error', 2000);
1535
+ }
1536
+ this.showAddToListLoader = false;
1537
+ this.toggleAddToListDialog(false);
1579
1538
  }
1580
1539
  onSearch(inputValue) {
1581
1540
  this.searchDebounce$.next(inputValue);
@@ -1586,47 +1545,45 @@ export class UserViewGridComponent {
1586
1545
  this.search(inputValue);
1587
1546
  });
1588
1547
  }
1589
- search(inputValue) {
1590
- return __awaiter(this, void 0, void 0, function* () {
1591
- if (!this.sourceListEntities) {
1592
- return;
1593
- }
1594
- this.listEntitySearch = inputValue;
1595
- const toLowerCase = inputValue.toLowerCase();
1596
- this.listEntities = this.sourceListEntities.filter((listEntity) => {
1597
- return listEntity.Name.toLowerCase().includes(toLowerCase);
1598
- });
1548
+ async search(inputValue) {
1549
+ if (!this.sourceListEntities) {
1550
+ return;
1551
+ }
1552
+ this.listEntitySearch = inputValue;
1553
+ const toLowerCase = inputValue.toLowerCase();
1554
+ this.listEntities = this.sourceListEntities.filter((listEntity) => {
1555
+ return listEntity.Name.toLowerCase().includes(toLowerCase);
1599
1556
  });
1600
1557
  }
1558
+ static ɵfac = function UserViewGridComponent_Factory(t) { return new (t || UserViewGridComponent)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.FormBuilder), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i0.Renderer2)); };
1559
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserViewGridComponent, selectors: [["mj-user-view-grid"]], viewQuery: function UserViewGridComponent_Query(rf, ctx) { if (rf & 1) {
1560
+ i0.ɵɵviewQuery(_c0, 5, GridComponent);
1561
+ i0.ɵɵviewQuery(_c0, 5, ElementRef);
1562
+ i0.ɵɵviewQuery(_c1, 5, ExcelExportComponent);
1563
+ i0.ɵɵviewQuery(_c2, 5);
1564
+ i0.ɵɵviewQuery(_c3, 5, TextAreaComponent);
1565
+ i0.ɵɵviewQuery(_c4, 5, ElementRef);
1566
+ i0.ɵɵviewQuery(_c5, 5);
1567
+ i0.ɵɵviewQuery(_c6, 5);
1568
+ } if (rf & 2) {
1569
+ let _t;
1570
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElement = _t.first);
1571
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElementRef = _t.first);
1572
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoExcelExport = _t.first);
1573
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.recordCompareComponent = _t.first);
1574
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.analysisQuestion = _t.first);
1575
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.analysisResults = _t.first);
1576
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.compareDialogContainer = _t.first);
1577
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.entityFormDialog = _t.first);
1578
+ } }, inputs: { Params: "Params", BottomMargin: "BottomMargin", InEditMode: "InEditMode", EditMode: "EditMode", AutoNavigate: "AutoNavigate", NewRecordValues: "NewRecordValues", ShowCreateNewRecordButton: "ShowCreateNewRecordButton", ShowEntityActionButtons: "ShowEntityActionButtons", ShowCommunicationButton: "ShowCommunicationButton", CreateRecordMode: "CreateRecordMode", AllowLoad: "AllowLoad" }, outputs: { rowClicked: "rowClicked", rowEdited: "rowEdited" }, decls: 3, vars: 1, consts: [["kendoGrid", ""], ["excelExport", ""], ["compareDialogContainer", ""], ["entityFormDialog", ""], ["templatePreviewDialog", ""], ["recordCompareRef", ""], ["mjFillContainer", "", 1, "user-view-grid-wrap"], ["mjFillContainer", "", "scrollable", "virtual", "kendoGridSelectBy", "", 3, "pageChange", "selectedKeysChange", "cellClick", "cellClose", "columnReorder", "columnResize", "selectionChange", "sortChange", "resizable", "data", "skip", "pageSize", "rowHeight", "loading", "height", "sortable", "sort", "reorderable", "selectable", "selectedKeys"], ["kendoGridToolbarTemplate", ""], [3, "width", "headerStyle", "style", 4, "ngIf"], [3, "field", "title", "width", "editable", "editor", "headerStyle", "style", 4, "ngFor", "ngForOf"], [3, "data", "fileName"], [3, "field", "title", 4, "ngFor", "ngForOf"], [4, "ngIf"], ["class", "dialog-wrapper", "title", "Select List(s) To Add Record(s) To", 3, "minHeight", "maxHeight", "minWidth", "maxWidth", "close", 4, "ngIf"], ["Mode", "complete", 3, "Visible"], [3, "DialogClosed", "DialogVisible", "entityInfo", "runViewParams"], ["kendoButton", "", 1, "k-button-solid-base", "list-button", 3, "disabled"], ["kendoButton", "", 1, "k-button-solid-base", "list-button"], ["kendoButton", ""], ["kendoButton", "", 3, "click"], [1, "fa-regular", "fa-file-excel"], ["kendoButton", "", 1, "k-button-solid-base", "list-button", 3, "click"], ["kendoButton", "", 1, "list-button"], [1, "fa-regular", "fa-plus"], [1, "fa-regular", "fa-envelope"], ["kendoButton", "", 1, "list-button", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], ["kendoButton", "", 1, "k-button-solid-base", "list-button", 3, "click", "disabled"], [3, "width", "headerStyle"], [3, "field", "title", "width", "editable", "editor", "headerStyle"], ["kendoGridFooterTemplate", ""], [2, "font-size", "smaller", "font-weight", "normal"], [3, "field", "title"], [1, "k-overlay"], ["title", "Compare Records", 3, "minHeight", "minWidth", "top", "left", "width", "height", "resizable", "close", 4, "ngIf"], ["title", "Compare Records", 3, "close", "minHeight", "minWidth", "top", "left", "width", "height", "resizable"], ["mjFillContainer", "", 3, "fillHeight", "bottomMargin"], [3, "entityName", "recordsToCompare", "visibleColumns", "selectionMode"], [1, "k-actions", "k-actions-end"], ["kendoButton", "", "themeColor", "primary", "type", "button", 3, "click", 4, "ngIf"], ["kendoButton", "", "type", "button", 3, "click", 4, "ngIf"], ["title", "Confirm Choice", 3, "minWidth", "width", "close", 4, "ngIf"], ["kendoButton", "", "themeColor", "primary", "type", "button", 3, "click"], ["kendoButton", "", "type", "button", 3, "click"], ["title", "Confirm Choice", 3, "close", "minWidth", "width"], [2, "margin", "30px", "text-align", "center"], ["kendoButton", "", "themeColor", "primary", 3, "click"], ["title", "Select List(s) To Add Record(s) To", 1, "dialog-wrapper", 3, "close", "minHeight", "maxHeight", "minWidth", "maxWidth"], [1, "search-header"], ["id", "listSearch", "placeholder", "Search Lists...", "kendoTextBox", "", 1, "search-bar", 3, "valueChange", "clearButton"], [1, "overflow-y-scroll"], ["type", "converging-spinner"], ["kendoButton", "", "themeColor", "primary", 3, "click", "disabled"], ["kendoButton", "", 3, "click", "disabled"], [1, "list-item"], [1, "list-text", 3, "ngClass"], ["kendoButton", "", 1, "btn-no-border", "btn-selected"], ["kendoButton", "", 1, "btn-no-border"], ["kendoButton", "", 1, "btn-no-border", "btn-selected", 3, "click"], [1, "fa-solid", "fa-minus"], ["kendoButton", "", 1, "btn-no-border", 3, "click"], [1, "btn-margin-right"], [1, "fa-solid", "fa-plus"]], template: function UserViewGridComponent_Template(rf, ctx) { if (rf & 1) {
1579
+ i0.ɵɵelementStart(0, "div", 6);
1580
+ i0.ɵɵtemplate(1, UserViewGridComponent_Conditional_1_Template, 1, 0, "kendo-loader")(2, UserViewGridComponent_Conditional_2_Template, 16, 24);
1581
+ i0.ɵɵelementEnd();
1582
+ } if (rf & 2) {
1583
+ i0.ɵɵadvance();
1584
+ i0.ɵɵconditional(ctx.isLoading || !ctx.AllowLoad || ctx.neverLoaded ? 1 : 2);
1585
+ } }, dependencies: [i3.NgClass, i3.NgForOf, i3.NgIf, i4.GridComponent, i4.ToolbarTemplateDirective, i4.SelectionDirective, i4.ColumnComponent, i4.FooterTemplateDirective, i4.CheckboxColumnComponent, i5.DialogComponent, i5.DialogActionsComponent, i5.WindowComponent, i6.ExcelExportComponent, i6.ColumnComponent, i7.ButtonComponent, i8.CompareRecordsComponent, i9.FillContainer, i10.TextBoxComponent, i11.EntityFormDialogComponent, i12.LoaderComponent, i13.EntityCommunicationsPreviewWindowComponent, i3.DecimalPipe], styles: [".user-view-grid-wrap[_ngcontent-%COMP%] {\n height: calc(100vh - 20px);\n}\n\n.user-view-grid-column-header[_ngcontent-%COMP%] {\n background-color: #fff;\n font-size: 20pt;\n font-weight: bold;\n}\n\n.title-wrapper[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 0;\n border-bottom: 1px solid var(--med-gray);\n}\n .title-wrapper[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 24px;\n line-height: 28px;\n }\n .main-fav-wrapper[_ngcontent-%COMP%] {\n background: #fff;\n padding: 20px;\n }\n .filter-wrapper[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 14px;\n align-items: center;\n}\n .title-wrapper[_ngcontent-%COMP%] .search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n font-size: 16px;\n background: transparent;\n border: none;\n box-sizing: border-box;\n padding-left: 40px;\n\n }\n .title-wrapper[_ngcontent-%COMP%] .search[_ngcontent-%COMP%] {\n background: var(--light-shade);\n width: 360px;\n height: 44px;\n position: relative;\n border-radius: 10px;\n }\n .title-wrapper[_ngcontent-%COMP%] .search[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n left: 12px;\n}\n.k-table-td[_ngcontent-%COMP%] {\n border-right: none !important;\n}.btn-cmn[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n min-width: 44px;\n background: transparent;\n border-radius: 8px;\n border: 1px solid var(--gray-color);\n}\n.btn-cmn.active[_ngcontent-%COMP%] {\n border: 1px solid var(--border-blue);\n}\n .title-wrapper .filter-wrapper .k-dropdown-button .k-button {\n border: 1px solid var(--gray-color);\n border-radius: 8px; padding: 10px 25px;\n background: var(--white-color);\n color: var(--sideNav);\n}\n .user-view-grid-wrap .k-grid-aria-root .k-grid-header .k-grid-header-table thead tr th {\n border-right: none;\n border-inline-start-width: 0;\n color: var(--thead-color);\n}\n .user-view-grid-wrap .k-grid-aria-root kendo-grid-list .k-grid-table tbody tr td { \n border-inline-start-width: 0;\n color: var(--tdata-color);\n font-weight: 500;\n border-bottom-width: 1px;\n} \n\n.overflow-y-scroll[_ngcontent-%COMP%] {\n overflow-y: auto;\n max-height: 300px;\n}\n\n.padding-bottom-small[_ngcontent-%COMP%] {\n padding-bottom: 10px;\n}\n\n.list-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n padding-bottom: 5px;\n align-items: center;\n}\n\n.btn-no-border[_ngcontent-%COMP%] {\n border: none;\n background: none;\n color: var(--border-blue);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.btn-selected[_ngcontent-%COMP%] {\n font-weight: bold;\n}\n\n.list-text[_ngcontent-%COMP%] {\n font-size: large;\n}\n.list-selected[_ngcontent-%COMP%] {\n font-weight: bold;\n color: var(--border-blue);\n}\n\n.btn-margin-right[_ngcontent-%COMP%] {\n margin-right: 35px;\n}\n\n.divider[_ngcontent-%COMP%] {\n color: lightgray\n}\n\n.search-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0;\n}\n\n.search-bar[_ngcontent-%COMP%] {\n width: 65%;\n padding-bottom: 10px;\n}\n\n.dialog-wrapper[_ngcontent-%COMP%] {\n padding: 15px 25px;\n}\n\n.btn-outline[_ngcontent-%COMP%] {\n border: 2px solid var(--border-blue);\n border-radius: 8px;\n padding: 5px 30px;\n\n background: none;\n color: var(--border-blue);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n}"] });
1601
1586
  }
1602
- UserViewGridComponent.ɵfac = function UserViewGridComponent_Factory(t) { return new (t || UserViewGridComponent)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.FormBuilder), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i0.Renderer2)); };
1603
- UserViewGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserViewGridComponent, selectors: [["mj-user-view-grid"]], viewQuery: function UserViewGridComponent_Query(rf, ctx) { if (rf & 1) {
1604
- i0.ɵɵviewQuery(_c0, 5, GridComponent);
1605
- i0.ɵɵviewQuery(_c0, 5, ElementRef);
1606
- i0.ɵɵviewQuery(_c1, 5, ExcelExportComponent);
1607
- i0.ɵɵviewQuery(_c2, 5);
1608
- i0.ɵɵviewQuery(_c3, 5, TextAreaComponent);
1609
- i0.ɵɵviewQuery(_c4, 5, ElementRef);
1610
- i0.ɵɵviewQuery(_c5, 5);
1611
- i0.ɵɵviewQuery(_c6, 5);
1612
- } if (rf & 2) {
1613
- let _t;
1614
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElement = _t.first);
1615
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElementRef = _t.first);
1616
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoExcelExport = _t.first);
1617
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.recordCompareComponent = _t.first);
1618
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.analysisQuestion = _t.first);
1619
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.analysisResults = _t.first);
1620
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.compareDialogContainer = _t.first);
1621
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.entityFormDialog = _t.first);
1622
- } }, inputs: { Params: "Params", BottomMargin: "BottomMargin", InEditMode: "InEditMode", EditMode: "EditMode", AutoNavigate: "AutoNavigate", NewRecordValues: "NewRecordValues", ShowCreateNewRecordButton: "ShowCreateNewRecordButton", ShowEntityActionButtons: "ShowEntityActionButtons", ShowCommunicationButton: "ShowCommunicationButton", CreateRecordMode: "CreateRecordMode", AllowLoad: "AllowLoad" }, outputs: { rowClicked: "rowClicked", rowEdited: "rowEdited" }, decls: 3, vars: 1, consts: [["kendoGrid", ""], ["excelExport", ""], ["compareDialogContainer", ""], ["entityFormDialog", ""], ["templatePreviewDialog", ""], ["recordCompareRef", ""], ["mjFillContainer", "", 1, "user-view-grid-wrap"], ["mjFillContainer", "", "scrollable", "virtual", "kendoGridSelectBy", "", 3, "pageChange", "selectedKeysChange", "cellClick", "cellClose", "columnReorder", "columnResize", "selectionChange", "sortChange", "resizable", "data", "skip", "pageSize", "rowHeight", "loading", "height", "sortable", "sort", "reorderable", "selectable", "selectedKeys"], ["kendoGridToolbarTemplate", ""], [3, "width", "headerStyle", "style", 4, "ngIf"], [3, "field", "title", "width", "editable", "editor", "headerStyle", "style", 4, "ngFor", "ngForOf"], [3, "data", "fileName"], [3, "field", "title", 4, "ngFor", "ngForOf"], [4, "ngIf"], ["class", "dialog-wrapper", "title", "Select List(s) To Add Record(s) To", 3, "minHeight", "maxHeight", "minWidth", "maxWidth", "close", 4, "ngIf"], ["Mode", "complete", 3, "Visible"], [3, "DialogClosed", "DialogVisible", "entityInfo", "runViewParams"], ["kendoButton", "", 1, "k-button-solid-base", "list-button", 3, "disabled"], ["kendoButton", "", 1, "k-button-solid-base", "list-button"], ["kendoButton", ""], ["kendoButton", "", 3, "click"], [1, "fa-regular", "fa-file-excel"], ["kendoButton", "", 1, "k-button-solid-base", "list-button", 3, "click"], ["kendoButton", "", 1, "list-button"], [1, "fa-regular", "fa-plus"], [1, "fa-regular", "fa-envelope"], ["kendoButton", "", 1, "list-button", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], ["kendoButton", "", 1, "k-button-solid-base", "list-button", 3, "click", "disabled"], [3, "width", "headerStyle"], [3, "field", "title", "width", "editable", "editor", "headerStyle"], ["kendoGridFooterTemplate", ""], [2, "font-size", "smaller", "font-weight", "normal"], [3, "field", "title"], [1, "k-overlay"], ["title", "Compare Records", 3, "minHeight", "minWidth", "top", "left", "width", "height", "resizable", "close", 4, "ngIf"], ["title", "Compare Records", 3, "close", "minHeight", "minWidth", "top", "left", "width", "height", "resizable"], ["mjFillContainer", "", 3, "fillHeight", "bottomMargin"], [3, "entityName", "recordsToCompare", "visibleColumns", "selectionMode"], [1, "k-actions", "k-actions-end"], ["kendoButton", "", "themeColor", "primary", "type", "button", 3, "click", 4, "ngIf"], ["kendoButton", "", "type", "button", 3, "click", 4, "ngIf"], ["title", "Confirm Choice", 3, "minWidth", "width", "close", 4, "ngIf"], ["kendoButton", "", "themeColor", "primary", "type", "button", 3, "click"], ["kendoButton", "", "type", "button", 3, "click"], ["title", "Confirm Choice", 3, "close", "minWidth", "width"], [2, "margin", "30px", "text-align", "center"], ["kendoButton", "", "themeColor", "primary", 3, "click"], ["title", "Select List(s) To Add Record(s) To", 1, "dialog-wrapper", 3, "close", "minHeight", "maxHeight", "minWidth", "maxWidth"], [1, "search-header"], ["id", "listSearch", "placeholder", "Search Lists...", "kendoTextBox", "", 1, "search-bar", 3, "valueChange", "clearButton"], [1, "overflow-y-scroll"], ["type", "converging-spinner"], ["kendoButton", "", "themeColor", "primary", 3, "click", "disabled"], ["kendoButton", "", 3, "click", "disabled"], [1, "list-item"], [1, "list-text", 3, "ngClass"], ["kendoButton", "", 1, "btn-no-border", "btn-selected"], ["kendoButton", "", 1, "btn-no-border"], ["kendoButton", "", 1, "btn-no-border", "btn-selected", 3, "click"], [1, "fa-solid", "fa-minus"], ["kendoButton", "", 1, "btn-no-border", 3, "click"], [1, "btn-margin-right"], [1, "fa-solid", "fa-plus"]], template: function UserViewGridComponent_Template(rf, ctx) { if (rf & 1) {
1623
- i0.ɵɵelementStart(0, "div", 6);
1624
- i0.ɵɵtemplate(1, UserViewGridComponent_Conditional_1_Template, 1, 0, "kendo-loader")(2, UserViewGridComponent_Conditional_2_Template, 16, 24);
1625
- i0.ɵɵelementEnd();
1626
- } if (rf & 2) {
1627
- i0.ɵɵadvance();
1628
- i0.ɵɵconditional(ctx.isLoading || !ctx.AllowLoad || ctx.neverLoaded ? 1 : 2);
1629
- } }, dependencies: [i3.NgClass, i3.NgForOf, i3.NgIf, i4.GridComponent, i4.ToolbarTemplateDirective, i4.SelectionDirective, i4.ColumnComponent, i4.FooterTemplateDirective, i4.CheckboxColumnComponent, i5.DialogComponent, i5.DialogActionsComponent, i5.WindowComponent, i6.ExcelExportComponent, i6.ColumnComponent, i7.ButtonComponent, i8.CompareRecordsComponent, i9.FillContainer, i10.TextBoxComponent, i11.EntityFormDialogComponent, i12.LoaderComponent, i13.EntityCommunicationsPreviewWindowComponent, i3.DecimalPipe], styles: [".user-view-grid-wrap[_ngcontent-%COMP%] {\n height: calc(100vh - 20px);\n}\n\n.user-view-grid-column-header[_ngcontent-%COMP%] {\n background-color: #fff;\n font-size: 20pt;\n font-weight: bold;\n}\n\n.title-wrapper[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 0;\n border-bottom: 1px solid var(--med-gray);\n}\n .title-wrapper[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 24px;\n line-height: 28px;\n }\n .main-fav-wrapper[_ngcontent-%COMP%] {\n background: #fff;\n padding: 20px;\n }\n .filter-wrapper[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 14px;\n align-items: center;\n}\n .title-wrapper[_ngcontent-%COMP%] .search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n font-size: 16px;\n background: transparent;\n border: none;\n box-sizing: border-box;\n padding-left: 40px;\n\n }\n .title-wrapper[_ngcontent-%COMP%] .search[_ngcontent-%COMP%] {\n background: var(--light-shade);\n width: 360px;\n height: 44px;\n position: relative;\n border-radius: 10px;\n }\n .title-wrapper[_ngcontent-%COMP%] .search[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n left: 12px;\n}\n.k-table-td[_ngcontent-%COMP%] {\n border-right: none !important;\n}.btn-cmn[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n min-width: 44px;\n background: transparent;\n border-radius: 8px;\n border: 1px solid var(--gray-color);\n}\n.btn-cmn.active[_ngcontent-%COMP%] {\n border: 1px solid var(--border-blue);\n}\n .title-wrapper .filter-wrapper .k-dropdown-button .k-button {\n border: 1px solid var(--gray-color);\n border-radius: 8px; padding: 10px 25px;\n background: var(--white-color);\n color: var(--sideNav);\n}\n .user-view-grid-wrap .k-grid-aria-root .k-grid-header .k-grid-header-table thead tr th {\n border-right: none;\n border-inline-start-width: 0;\n color: var(--thead-color);\n}\n .user-view-grid-wrap .k-grid-aria-root kendo-grid-list .k-grid-table tbody tr td { \n border-inline-start-width: 0;\n color: var(--tdata-color);\n font-weight: 500;\n border-bottom-width: 1px;\n} \n\n.overflow-y-scroll[_ngcontent-%COMP%] {\n overflow-y: auto;\n max-height: 300px;\n}\n\n.padding-bottom-small[_ngcontent-%COMP%] {\n padding-bottom: 10px;\n}\n\n.list-item[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n padding-bottom: 5px;\n align-items: center;\n}\n\n.btn-no-border[_ngcontent-%COMP%] {\n border: none;\n background: none;\n color: var(--border-blue);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.btn-selected[_ngcontent-%COMP%] {\n font-weight: bold;\n}\n\n.list-text[_ngcontent-%COMP%] {\n font-size: large;\n}\n.list-selected[_ngcontent-%COMP%] {\n font-weight: bold;\n color: var(--border-blue);\n}\n\n.btn-margin-right[_ngcontent-%COMP%] {\n margin-right: 35px;\n}\n\n.divider[_ngcontent-%COMP%] {\n color: lightgray\n}\n\n.search-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0;\n}\n\n.search-bar[_ngcontent-%COMP%] {\n width: 65%;\n padding-bottom: 10px;\n}\n\n.dialog-wrapper[_ngcontent-%COMP%] {\n padding: 15px 25px;\n}\n\n.btn-outline[_ngcontent-%COMP%] {\n border: 2px solid var(--border-blue);\n border-radius: 8px;\n padding: 5px 30px;\n\n background: none;\n color: var(--border-blue);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n}"] });
1630
1587
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserViewGridComponent, [{
1631
1588
  type: Component,
1632
1589
  args: [{ selector: 'mj-user-view-grid', template: "<div class=\"user-view-grid-wrap\" mjFillContainer>\n @if (isLoading || !AllowLoad || neverLoaded) {\n <kendo-loader></kendo-loader>\n }\n @else {\n <kendo-grid #kendoGrid\n mjFillContainer\n [resizable]=\"true\"\n [data]=\"gridView\" \n [skip]=\"skip\"\n [pageSize]=\"pageSize\"\n scrollable=\"virtual\"\n [rowHeight]=\"36\"\n (pageChange)=\"pageChange($event)\"\n [loading]=\"isLoading\"\n [height]=\"gridHeight\"\n [sortable]=\"UserCanEdit\"\n [sort]=\"sortSettings\" \n [resizable]=\"UserCanEdit\"\n [reorderable]=\"UserCanEdit\"\n [selectable]=\"true\"\n kendoGridSelectBy\n [(selectedKeys)]=\"selectedKeys\"\n (cellClick)=\"cellClickHandler($event)\"\n (cellClose)=\"cellCloseHandler($event)\"\n (columnReorder)=\"columnReorder($event)\"\n (columnResize)=\"columnResize($event)\"\n (selectionChange)=\"selectionChange($event)\"\n (sortChange)=\"sortChanged($event)\"\n >\n <ng-template kendoGridToolbarTemplate>\n @if(!anyModeEnabled){\n @if(EntityInfo && ShowCreateNewRecordButton && UserCanCreateNewRecord) {\n <button kendoButton (click)=\"doCreateNewRecord()\" >\n <span class=\"fa-regular fa-plus\"></span>\n New {{entityRecord?.EntityInfo?.Name}}\n </button> \n }\n\n <button kendoButton (click)=\"doExcelExport()\" >\n <span class=\"fa-regular fa-file-excel\"></span>\n Export to Excel\n </button>\n <button (click)=\"enableCheckbox(false, 'duplicate')\" kendoButton class=\"k-button-solid-base list-button\">\n Search For Duplicates\n </button>\n <button (click)=\"enableCheckbox(false, 'addToList')\" kendoButton class=\"k-button-solid-base list-button\">\n Add To List\n </button>\n <button (click)=\"enableMergeOrCompare(false, 'merge')\" kendoButton class=\"k-button-solid-base list-button\">\n Merge\n </button>\n <button (click)=\"enableMergeOrCompare(false, 'compare')\" kendoButton class=\"k-button-solid-base list-button\">\n Compare\n </button>\n\n @if (ShowCommunicationButton && EntitySupportsCommunication) {\n <button (click)=\"doCommunication()\" kendoButton class=\"k-button-solid-base list-button\">\n <span class=\"fa-regular fa-envelope\"></span>\n </button> \n }\n\n @if (ShowEntityActionButtons && EntityActions && EntityActions.length > 0) {\n @for (action of EntityActions; track action) {\n <button (click)=\"doEntityAction(action)\" kendoButton class=\"k-button-solid-base list-button\">\n {{action.Action}}\n </button>\n }\n }\n\n @if(showRefreshButton){\n <button kendoButton class=\"list-button\" (click)=\"RefreshFromSavedParams()\">\n <span class=\"fa-solid fa-arrows-rotate\"></span>\n Refresh\n </button>\n }\n }\n @if(duplicateMode){\n <button (click)=\"enableCheckbox(false, 'duplicate')\" [disabled]=\"duplicateMode && recordsToCompare.length < 2\" kendoButton class=\"k-button-solid-base list-button\">\n Search For Duplicates\n </button>\n }\n @if(addToListMode){\n <button (click)=\"enableCheckbox(false, 'addToList')\" [disabled]=\"addToListMode && recordsToCompare.length === 0\" kendoButton class=\"k-button-solid-base list-button\">\n Add To List\n </button>\n }\n @if(compareMode){\n <button (click)=\"enableMergeOrCompare(false, 'compare')\" [disabled]=\"compareMode && recordsToCompare.length < 2\" kendoButton class=\"k-button-solid-base list-button\">\n Compare\n </button>\n }\n @if(mergeMode){\n <button (click)=\"enableMergeOrCompare(false, 'merge')\" [disabled]=\"mergeMode && recordsToCompare.length < 2\" kendoButton class=\"k-button-solid-base list-button\">\n Merge\n </button>\n }\n @if(anyModeEnabled){\n <button (click)=\"enableCheckbox(true, '')\" kendoButton class=\"k-button-solid-base list-button\">\n Cancel\n </button>\n }\n </ng-template>\n \n <kendo-grid-checkbox-column \n *ngIf=\"anyModeEnabled\" \n [width]=\"50\" \n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': 'white' }\" \n [style]=\"{'text-align': 'center', 'vertical-align': 'center'}\">\n </kendo-grid-checkbox-column>\n \n <kendo-grid-column \n *ngFor=\"let item of visibleColumns\" \n [field]=\"item.Name\" \n [title]=\"GetColumnTitle(item)\"\n [width]=\"item.width ? item.width : 100\"\n [editable]=\"item.EntityField.AllowUpdateAPI\"\n [editor]=\"getEditor(item.EntityField)\"\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': 'white' }\"\n [style]=\"this.GetColumnCellStyle(item)\"\n >\n <ng-template *ngIf=\"item===visibleColumns[0]\" kendoGridFooterTemplate >\n {{this.viewData.length | number}}{{this.totalRowCount > this.viewData.length ? ' of ' + (this.totalRowCount | number) : ' rows'}}<br/><span style=\"font-size: smaller; font-weight: normal;\">{{viewExecutionTime | number:'1.2-2'}} seconds</span>\n </ng-template>\n </kendo-grid-column>\n\n <kendo-excelexport #excelExport [data]=\"exportData\" [fileName]=\"(_viewEntity ? _viewEntity.Get('Name') : _entityInfo?.Name) + '.xlsx'\">\n <kendo-excelexport-column *ngFor=\"let exportCol of exportColumns\" [field]=\"exportCol.Name\" [title]=\"exportCol.Name\">\n </kendo-excelexport-column>\n </kendo-excelexport>\n </kendo-grid>\n\n \n <div #compareDialogContainer>\n <div *ngIf=\"isCompareDialogOpened\">\n <div class=\"k-overlay\"></div>\n <kendo-window\n [minHeight]=\"300\"\n [minWidth]=\"800\"\n [top]=\"100\"\n [left]=\"100\"\n [width]=\"1200\"\n [height]=\"675\"\n [resizable]=\"true\"\n (close)=\"closeCompareDialog($event)\"\n title=\"Compare Records\"\n *ngIf=\"isCompareDialogOpened\"\n >\n <div mjFillContainer [fillHeight]=\"true\" [bottomMargin]=\"100\">\n <mj-compare-records\n #recordCompareRef\n [entityName]=\"_entityInfo ? _entityInfo.Name : ''\"\n [recordsToCompare]=\"recordsToCompare\" \n [visibleColumns]=\"visibleColumns\" \n [selectionMode]=\"mergeMode ? true : false\"\n >\n </mj-compare-records>\n </div>\n <div class=\"k-actions k-actions-end\">\n <button *ngIf=\"mergeMode\" kendoButton themeColor=\"primary\" type=\"button\" (click)=\"closeCompareDialog('merge')\">\n Merge Records\n </button>\n <button *ngIf=\"duplicateMode\" kendoButton themeColor=\"primary\" type=\"button\" (click)=\"findDuplicateRecords()\">\n Search for Duplicates\n </button>\n <button *ngIf=\"compareMode\" kendoButton type=\"button\" (click)=\"closeCompareDialog('close')\">\n Close\n </button>\n <button *ngIf=\"mergeMode || duplicateMode\" kendoButton type=\"button\" (click)=\"closeCompareDialog('cancel')\">\n Cancel\n </button>\n </div> \n <kendo-dialog\n title=\"Confirm Choice\"\n *ngIf=\"isConfirmDialogOpen\"\n (close)=\"closeConfirmMergeDialog('cancel')\"\n [minWidth]=\"250\"\n [width]=\"450\"\n >\n <p style=\"margin: 30px; text-align: center;\">\n Are you sure you want to merge the records? This action cannot be undone. If you select \"Yes\", the records will be merged and the duplicate records will be deleted.\n </p>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"closeConfirmMergeDialog('no')\">No</button>\n <button kendoButton (click)=\"closeConfirmMergeDialog('yes')\" themeColor=\"primary\">\n Yes\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n </kendo-window>\n </div> \n </div>\n <kendo-dialog\n class=\"dialog-wrapper\"\n title=\"Select List(s) To Add Record(s) To\"\n *ngIf=\"showAddToListDialog\"\n (close)=\"toggleAddToListDialog(false)\"\n [minHeight]=\"500\"\n [maxHeight]=\"500\"\n [minWidth]=\"500\"\n [maxWidth]=\"650\"\n >\n <div class=\"search-header\">\n <kendo-textbox\n id=\"listSearch\"\n placeholder=\"Search Lists...\"\n kendoTextBox\n (valueChange)=\"onSearch($event)\"\n [clearButton]=\"true\"\n class=\"search-bar\"\n ></kendo-textbox>\n </div>\n <hr>\n <div class=\"overflow-y-scroll\">\n @if(showAddToListLoader){\n <kendo-loader type=\"converging-spinner\"></kendo-loader>\n }\n @else {\n @for(listEntity of listEntities; track listEntity){\n <div class=\"list-item\">\n <div class=\"list-text\" [ngClass]=\"{'list-selected': selectedListEntities.includes(listEntity)}\">\n {{listEntity.Name}}\n </div>\n @if(selectedListEntities.includes(listEntity)){\n <button kendoButton class=\"btn-no-border btn-selected\" (click)=\"removeFromList(listEntity)\">\n <span class=\"fa-solid fa-minus\"></span>\n Remove\n </button>\n }\n @else {\n <button kendoButton class=\"btn-no-border\" (click)=\"addToList(listEntity)\">\n <div class=\"btn-margin-right\">\n <span class=\"fa-solid fa-plus\"></span>\n Add\n </div>\n </button>\n }\n </div>\n <hr>\n }\n }\n </div>\n\n\n <kendo-dialog-actions>\n <button kendoButton (click)=\"addRecordsToSelectedLists()\" [disabled]=\"showAddToListLoader\" themeColor=\"primary\">\n Save\n </button>\n <button kendoButton (click)=\"toggleAddToListDialog(false)\" [disabled]=\"showAddToListLoader\">\n Cancel\n </button>\n </kendo-dialog-actions>\n </kendo-dialog>\n\n <!-- Entity Form Dialog Component here for future use as needed -->\n <mj-entity-form-dialog\n #entityFormDialog\n Mode=\"complete\"\n [Visible]=\"showNewRecordDialog\"\n ></mj-entity-form-dialog>\n\n <mj-entity-communications-preview-window \n #templatePreviewDialog\n [DialogVisible]=\"showTemplatePreviewDialog\"\n (DialogClosed)=\"showTemplatePreviewDialog = false\"\n [entityInfo]=\"_entityInfo\"\n [runViewParams]=\"Params\"\n >\n </mj-entity-communications-preview-window> \n\n }\n</div>\n", styles: [".user-view-grid-wrap {\n height: calc(100vh - 20px);\n}\n\n.user-view-grid-column-header {\n background-color: #fff;\n font-size: 20pt;\n font-weight: bold;\n}\n\n.title-wrapper {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14px 0;\n border-bottom: 1px solid var(--med-gray);\n}\n .title-wrapper h4 {\n margin: 0;\n font-size: 24px;\n line-height: 28px;\n }\n .main-fav-wrapper {\n background: #fff;\n padding: 20px;\n }\n .filter-wrapper {\n display: flex;\n justify-content: flex-start;\n gap: 14px;\n align-items: center;\n}\n .title-wrapper .search input {\n width: 100%;\n height: 100%;\n font-size: 16px;\n background: transparent;\n border: none;\n box-sizing: border-box;\n padding-left: 40px;\n\n }\n .title-wrapper .search {\n background: var(--light-shade);\n width: 360px;\n height: 44px;\n position: relative;\n border-radius: 10px;\n }\n .title-wrapper .search svg {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n left: 12px;\n}\n.k-table-td {\n border-right: none !important;\n}.btn-cmn {\n width: 44px;\n height: 44px;\n min-width: 44px;\n background: transparent;\n border-radius: 8px;\n border: 1px solid var(--gray-color);\n}\n.btn-cmn.active {\n border: 1px solid var(--border-blue);\n}\n::ng-deep .title-wrapper .filter-wrapper .k-dropdown-button .k-button {\n border: 1px solid var(--gray-color);\n border-radius: 8px; padding: 10px 25px;\n background: var(--white-color);\n color: var(--sideNav);\n}\n::ng-deep .user-view-grid-wrap .k-grid-aria-root .k-grid-header .k-grid-header-table thead tr th {\n border-right: none;\n border-inline-start-width: 0;\n color: var(--thead-color);\n}\n::ng-deep .user-view-grid-wrap .k-grid-aria-root kendo-grid-list .k-grid-table tbody tr td { \n border-inline-start-width: 0;\n color: var(--tdata-color);\n font-weight: 500;\n border-bottom-width: 1px;\n} \n\n.overflow-y-scroll {\n overflow-y: auto;\n max-height: 300px;\n}\n\n.padding-bottom-small {\n padding-bottom: 10px;\n}\n\n.list-item {\n display: flex;\n justify-content: space-between;\n padding-bottom: 5px;\n align-items: center;\n}\n\n.btn-no-border {\n border: none;\n background: none;\n color: var(--border-blue);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.btn-selected {\n font-weight: bold;\n}\n\n.list-text {\n font-size: large;\n}\n.list-selected {\n font-weight: bold;\n color: var(--border-blue);\n}\n\n.btn-margin-right {\n margin-right: 35px;\n}\n\n.divider {\n color: lightgray\n}\n\n.search-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0;\n}\n\n.search-bar {\n width: 65%;\n padding-bottom: 10px;\n}\n\n.dialog-wrapper {\n padding: 15px 25px;\n}\n\n.btn-outline {\n border: 2px solid var(--border-blue);\n border-radius: 8px;\n padding: 5px 30px;\n\n background: none;\n color: var(--border-blue);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n}"] }]