@memberjunction/ng-user-view-grid 2.48.0 → 2.49.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.
- package/dist/lib/ng-user-view-grid.component.js +764 -807
- package/dist/lib/ng-user-view-grid.component.js.map +1 -1
- package/dist/module.js +18 -18
- package/dist/module.js.map +1 -1
- package/package.json +14 -14
|
@@ -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
|
-
|
|
477
|
-
|
|
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(() =>
|
|
634
|
+
this._saveTimeout = setTimeout(async () => {
|
|
638
635
|
// when we actually call inner save view we do await
|
|
639
|
-
|
|
640
|
-
}
|
|
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
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
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
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
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
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
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
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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
|
-
|
|
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
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
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
|
-
|
|
796
|
-
|
|
797
|
-
this
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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
|
-
|
|
831
|
-
|
|
832
|
-
|
|
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
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
if (
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
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
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
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
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
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
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
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
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
if
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
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
|
-
|
|
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
|
-
|
|
997
|
-
|
|
998
|
-
this.Refresh(this.Params);
|
|
999
|
-
});
|
|
980
|
+
async RefreshFromSavedParams() {
|
|
981
|
+
if (this.Params)
|
|
982
|
+
this.Refresh(this.Params);
|
|
1000
983
|
}
|
|
1001
|
-
Refresh(params) {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
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 (
|
|
1031
|
-
|
|
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("
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
1211
|
-
if (
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
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
|
-
|
|
1272
|
-
this.addToListMode = false;
|
|
1216
|
+
// close the dialogs
|
|
1273
1217
|
this.isCompareDialogOpened = false;
|
|
1274
|
-
|
|
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
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
this.
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
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
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
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
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
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
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
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
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
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
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
if
|
|
1426
|
-
|
|
1427
|
-
|
|
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
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
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
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
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
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
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
|
-
|
|
1505
|
-
|
|
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
|
-
|
|
1509
|
-
this.enableCheckbox(true, 'addToList');
|
|
1510
|
-
}
|
|
1511
|
-
this.setupSearchDebounce();
|
|
1512
|
-
});
|
|
1463
|
+
}
|
|
1513
1464
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1465
|
+
async toggleAddToListDialog(show) {
|
|
1466
|
+
this.showAddToListDialog = show;
|
|
1467
|
+
if (show) {
|
|
1468
|
+
if (!this.sourceListEntities) {
|
|
1469
|
+
await this.loadListEntities();
|
|
1519
1470
|
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
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
|
-
|
|
1532
|
-
|
|
1475
|
+
}
|
|
1476
|
+
else {
|
|
1477
|
+
this.enableCheckbox(true, 'addToList');
|
|
1478
|
+
}
|
|
1479
|
+
this.setupSearchDebounce();
|
|
1533
1480
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
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
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
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
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
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
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
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
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
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}"] }]
|