@memberjunction/ng-user-view-grid 0.9.1 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,769 +1,760 @@
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
- import { Component, ViewChild, ElementRef, Output, EventEmitter, Input } from '@angular/core';
11
- import { Metadata, RunView, EntityFieldTSType, LogError, ViewInfo } from '@memberjunction/core';
12
- import { GridComponent } from "@progress/kendo-angular-grid";
13
- import { Keys } from '@progress/kendo-angular-common';
14
- import { Subject } from 'rxjs';
15
- import { ExcelExportComponent } from '@progress/kendo-angular-excel-export';
16
- import { MJEventType, MJGlobal } from '@memberjunction/global';
17
- import * as i0 from "@angular/core";
18
- import * as i1 from "@angular/forms";
19
- import * as i2 from "@angular/router";
20
- import * as i3 from "@angular/common";
21
- import * as i4 from "@progress/kendo-angular-grid";
22
- import * as i5 from "@progress/kendo-angular-dialog";
23
- import * as i6 from "@progress/kendo-angular-excel-export";
24
- import * as i7 from "@progress/kendo-angular-buttons";
25
- const _c0 = ["kendoGrid"];
26
- const _c1 = ["excelExport"];
27
- function UserViewGridComponent_ng_template_3_button_2_Template(rf, ctx) { if (rf & 1) {
28
- const _r10 = i0.ɵɵgetCurrentView();
29
- i0.ɵɵelementStart(0, "button", 14);
30
- i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_button_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r9 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r9.enableCompare(true)); });
31
- i0.ɵɵtext(1, "Cancel");
32
- i0.ɵɵelementEnd();
33
- } }
34
- function UserViewGridComponent_ng_template_3_button_5_Template(rf, ctx) { if (rf & 1) {
35
- const _r12 = i0.ɵɵgetCurrentView();
36
- i0.ɵɵelementStart(0, "button", 15);
37
- i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_button_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r11 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r11.RefreshFromSavedParams()); });
38
- i0.ɵɵtext(1, " Refresh ");
39
- i0.ɵɵelementEnd();
40
- } if (rf & 2) {
41
- i0.ɵɵproperty("primary", true);
42
- } }
43
- function UserViewGridComponent_ng_template_3_Template(rf, ctx) { if (rf & 1) {
44
- const _r14 = i0.ɵɵgetCurrentView();
45
- i0.ɵɵelementStart(0, "button", 10);
46
- i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r13 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r13.doExcelExport()); });
47
- i0.ɵɵtext(1, "Export to Excel");
48
- i0.ɵɵelementEnd();
49
- i0.ɵɵtemplate(2, UserViewGridComponent_ng_template_3_button_2_Template, 2, 0, "button", 11);
50
- i0.ɵɵelementStart(3, "button", 12);
51
- i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r14); const ctx_r15 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r15.enableCompare()); });
52
- i0.ɵɵtext(4, "Compare");
53
- i0.ɵɵelementEnd();
54
- i0.ɵɵtemplate(5, UserViewGridComponent_ng_template_3_button_5_Template, 2, 1, "button", 13);
55
- } if (rf & 2) {
56
- const ctx_r1 = i0.ɵɵnextContext();
57
- i0.ɵɵproperty("disabled", ctx_r1.compareMode);
58
- i0.ɵɵadvance(2);
59
- i0.ɵɵproperty("ngIf", ctx_r1.compareMode);
60
- i0.ɵɵadvance(1);
61
- i0.ɵɵproperty("disabled", ctx_r1.compareMode && ctx_r1.compareRecords.length < 2);
62
- i0.ɵɵadvance(2);
63
- i0.ɵɵproperty("ngIf", ctx_r1.showRefreshButton);
64
- } }
65
- const _c2 = function () { return { "text-align": "center", "vertical-align": "center" }; };
66
- const _c3 = function () { return { "font-weight": "bold", "background-color": "#a9c2af" }; };
67
- function UserViewGridComponent_kendo_grid_checkbox_column_4_Template(rf, ctx) { if (rf & 1) {
68
- i0.ɵɵelement(0, "kendo-grid-checkbox-column", 16);
69
- } if (rf & 2) {
70
- i0.ɵɵstyleMap(i0.ɵɵpureFunction0(4, _c2));
71
- i0.ɵɵproperty("width", 50)("headerStyle", i0.ɵɵpureFunction0(5, _c3));
72
- } }
73
- function UserViewGridComponent_kendo_grid_column_5_1_ng_template_0_Template(rf, ctx) { if (rf & 1) {
74
- i0.ɵɵtext(0);
75
- i0.ɵɵpipe(1, "number");
76
- i0.ɵɵpipe(2, "number");
77
- i0.ɵɵelement(3, "br");
78
- i0.ɵɵelementStart(4, "span", 19);
79
- i0.ɵɵtext(5);
80
- i0.ɵɵpipe(6, "number");
81
- i0.ɵɵelementEnd();
82
- } if (rf & 2) {
83
- const ctx_r18 = i0.ɵɵnextContext(3);
84
- i0.ɵɵtextInterpolate2(" ", i0.ɵɵpipeBind1(1, 3, ctx_r18.viewData.length), "", ctx_r18.totalRowCount > ctx_r18.viewData.length ? " of " + i0.ɵɵpipeBind1(2, 5, ctx_r18.totalRowCount) : " rows", "");
85
- i0.ɵɵadvance(5);
86
- i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(6, 7, ctx_r18.viewExecutionTime, "1.2-2"), " seconds");
87
- } }
88
- function UserViewGridComponent_kendo_grid_column_5_1_Template(rf, ctx) { if (rf & 1) {
89
- i0.ɵɵtemplate(0, UserViewGridComponent_kendo_grid_column_5_1_ng_template_0_Template, 7, 10, "ng-template", 18);
90
- } }
91
- function UserViewGridComponent_kendo_grid_column_5_Template(rf, ctx) { if (rf & 1) {
92
- i0.ɵɵelementStart(0, "kendo-grid-column", 17);
93
- i0.ɵɵtemplate(1, UserViewGridComponent_kendo_grid_column_5_1_Template, 1, 0, null, 9);
94
- i0.ɵɵelementEnd();
95
- } if (rf & 2) {
96
- const item_r16 = ctx.$implicit;
97
- const ctx_r3 = i0.ɵɵnextContext();
98
- i0.ɵɵstyleMap(ctx_r3.GetColumnCellStyle(item_r16));
99
- i0.ɵɵproperty("field", item_r16.Name)("title", ctx_r3.GetColumnTitle(item_r16))("width", item_r16.width ? item_r16.width : 100)("editable", item_r16.EntityField.AllowUpdateAPI)("editor", ctx_r3.getEditor(item_r16.EntityField))("headerStyle", i0.ɵɵpureFunction0(9, _c3));
100
- i0.ɵɵadvance(1);
101
- i0.ɵɵproperty("ngIf", item_r16 === ctx_r3.visibleColumns[0]);
102
- } }
103
- function UserViewGridComponent_kendo_excelexport_column_8_Template(rf, ctx) { if (rf & 1) {
104
- i0.ɵɵelement(0, "kendo-excelexport-column", 20);
105
- } if (rf & 2) {
106
- const exportCol_r19 = ctx.$implicit;
107
- i0.ɵɵproperty("field", exportCol_r19.Name)("title", exportCol_r19.Name);
108
- } }
109
- function UserViewGridComponent_div_9_kendo_window_2_Template(rf, ctx) { if (rf & 1) {
110
- const _r22 = i0.ɵɵgetCurrentView();
111
- i0.ɵɵelementStart(0, "kendo-window", 23);
112
- i0.ɵɵlistener("close", function UserViewGridComponent_div_9_kendo_window_2_Template_kendo_window_close_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r21 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r21.closeDialog()); });
113
- i0.ɵɵelementStart(1, "div", 24)(2, "div");
114
- i0.ɵɵelement(3, "mj-record-compare", 25);
115
- i0.ɵɵelementEnd()()();
116
- } if (rf & 2) {
117
- const ctx_r20 = i0.ɵɵnextContext(2);
118
- i0.ɵɵproperty("width", 900)("minHeight", 300)("minWidth", 400)("resizable", true);
119
- i0.ɵɵadvance(3);
120
- i0.ɵɵproperty("recordsToCompare", ctx_r20.compareRecords)("visibleColumns", ctx_r20.visibleColumns);
121
- } }
122
- function UserViewGridComponent_div_9_Template(rf, ctx) { if (rf & 1) {
123
- i0.ɵɵelementStart(0, "div");
124
- i0.ɵɵelement(1, "div", 21);
125
- i0.ɵɵtemplate(2, UserViewGridComponent_div_9_kendo_window_2_Template, 4, 6, "kendo-window", 22);
126
- i0.ɵɵelementEnd();
127
- } if (rf & 2) {
128
- const ctx_r6 = i0.ɵɵnextContext();
129
- i0.ɵɵadvance(2);
130
- i0.ɵɵproperty("ngIf", ctx_r6.isDialogOpened);
131
- } }
132
- export class UserViewGridComponent {
133
- get PendingRecords() {
134
- return this._pendingRecords;
135
- }
136
- StartEditMode() {
137
- this.InEditMode = true;
138
- }
139
- EndEditMode() {
140
- this.InEditMode = false;
141
- this.editModeEnded.next();
142
- }
143
- EditingComplete() {
144
- if (this.InEditMode) {
145
- // we need to wait for edit mode to end before we can return true
146
- return new Promise((resolve, reject) => {
147
- const subscription = this.editModeEnded.subscribe(() => {
148
- resolve(true);
149
- subscription.unsubscribe();
150
- });
151
- });
152
- }
153
- else
154
- return Promise.resolve(true); // not in edit mode, so editing is complete!
155
- }
156
- IsDynamicView() {
157
- return !this._viewEntity; // if we have a viewEntity it is a stored view
158
- }
159
- pageChange(event) {
160
- this.skip = event.skip;
161
- this.virtualLoadData();
162
- }
163
- virtualLoadData() {
164
- // check to see if we have already formatted the slice of the data we need right now
165
- // we are storing the formattted data in the formattedData array and it has same set
166
- // of indexes as the viewData array (raw unformatted data). When we first get viewData
167
- // from the server we create an array of the same length as viewData, but have nulls in all of the
168
- // indexes. As we format each row of viewData we store the formatted row in the same index
169
- // in the formattedData array. So if we have already formatted the data we need for the current
170
- // page, we just use that data, otherwise we format the data we need for the current page
171
- try {
172
- // check to see if we have already formatted the data we need for the current page
173
- for (let i = this.skip; (i < (this.skip + this.pageSize)) && (i < this.viewData.length); i++) {
174
- if (!this.formattedData[i]) {
175
- // we have not formatted this row yet, so format it
176
- const r = this.viewColumns.map((c) => {
177
- if (c && c.EntityField && this.viewData[i] && this.viewData[i][c.EntityField.Name]) {
178
- if (!c.hidden && c.EntityField.Name !== 'ID') {
179
- const ef = c.EntityField;
180
- return { field: c.EntityField.Name, value: ef.FormatValue(this.viewData[i][c.EntityField.Name], undefined, undefined, 300) };
181
- }
182
- else
183
- return { field: c.EntityField.Name, value: this.viewData[i][c.EntityField.Name] }; // hidden column, so just return the value, don't bother formatting
184
- }
185
- else
186
- return { field: c.Name, value: null };
187
- });
188
- // now r is an array of {field: string, value: any} objects, so we need to convert it to an object
189
- // with the field names as the keys and the values as the values
190
- const row = {};
191
- for (let j = 0; j < r.length; j++) {
192
- if (r[j] && r[j].field && r[j].field.length > 0)
193
- row[r[j].field] = r[j].value;
194
- }
195
- this.formattedData[i] = row;
196
- }
197
- }
198
- // now that we have made sure current page of data is formatted, we can return it
199
- this.gridView = {
200
- data: this.formattedData.slice(this.skip, this.skip + this.pageSize),
201
- total: this.viewData.length,
202
- };
203
- }
204
- catch (e) {
205
- LogError(e);
206
- }
207
- }
208
- constructor(formBuilder, router) {
209
- this.formBuilder = formBuilder;
210
- this.router = router;
211
- this.title = 'UserViewGrid';
212
- this.BottomMargin = 0;
213
- this.InEditMode = false;
214
- this.EditMode = "None";
215
- this.AutoNavigate = true;
216
- this.rowClicked = new EventEmitter();
217
- this.rowEdited = new EventEmitter();
218
- this.kendoGridElement = null;
219
- this.kendoGridElementRef = null;
220
- this.kendoExcelExport = null;
221
- this._pendingRecords = [];
222
- this.viewData = [];
223
- this.totalRowCount = 0;
224
- this.formattedData = [];
225
- this.viewColumns = [];
226
- this.visibleColumns = [];
227
- this.sortSettings = [];
228
- this.entityRecord = null;
229
- this.skip = 0;
230
- this.pageSize = 40;
231
- this.isLoading = false;
232
- this.gridView = { data: [], total: 0 };
233
- this.gridHeight = 750;
234
- this.resizeSub = null;
235
- this._newGridState = {};
236
- this.editModeEnded = new Subject();
237
- this.compareMode = false;
238
- this.compareRecords = [];
239
- this.selectableSettings = {
240
- enabled: false
241
- };
242
- this.selectedKeys = [];
243
- this.isDialogOpened = false;
244
- this.showRefreshButton = true;
245
- this.viewExecutionTime = 0;
246
- this._viewDirty = false;
247
- this._deferLoadCount = 0;
248
- this._allowLoad = true;
249
- // Export Functionality
250
- this.exportColumns = [];
251
- this.exportData = [];
252
- }
253
- SaveView() {
254
- // debounced outer function...
255
- clearTimeout(this._saveTimeout);
256
- this._saveTimeout = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
257
- // when we actually call inner save view we do await
258
- yield this.innerSaveView();
259
- }), 5000); // 5 seconds delay
260
- }
261
- ;
262
- innerSaveView() {
263
- return __awaiter(this, void 0, void 0, function* () {
264
- if (this._viewDirty) {
265
- const md = new Metadata();
266
- if (this._viewEntity &&
267
- this._viewEntity.Get('UserID') === md.CurrentUser.ID) {
268
- // this view is a saved view, AND it belongs to the current user
269
- // update the grid state if we have settings updates for columns and/or sorts
270
- const tempGridState = JSON.parse(this._viewEntity.Get('GridState'));
271
- const tempColSettings = this._newGridState.columnSettings ? this._newGridState.columnSettings : tempGridState.columnSettings;
272
- tempColSettings.forEach((col) => { col.DisplayName, col.ID, col.Name, col.hidden, col.orderIndex, col.width; }); // remove EntityFieldInfo from the column settings
273
- tempGridState.columnSettings = tempColSettings;
274
- tempGridState.sortSettings = this._newGridState.sortSettings ? this._newGridState.sortSettings : tempGridState.sortSettings;
275
- // now stringify the grid state and save it
276
- this._viewEntity.Set('GridState', JSON.stringify(tempGridState));
277
- const newSortState = tempGridState.sortSettings.map((s) => { return { field: s.field, direction: s.dir === 'asc' ? 1 : 2 }; });
278
- const oldSortState = JSON.parse(this._viewEntity.Get('SortState'));
279
- this._viewEntity.Set('SortState', JSON.stringify(newSortState));
280
- if (yield this._viewEntity.Save()) {
281
- // check to see if sort state changed and if so, refresh the grid
282
- if (JSON.stringify(newSortState) !== JSON.stringify(oldSortState)) {
283
- if (this.Params) // makes sure we have params before we refresh
284
- this.Refresh(this.Params);
285
- }
286
- this._viewDirty = false;
287
- }
288
- else {
289
- this.CreateSimpleNotification('Unable to save view settings', 'error', 5000);
290
- }
291
- }
292
- }
293
- });
294
- }
295
- CreateSimpleNotification(message, style, duration) {
296
- const data = {
297
- message: message,
298
- style: style,
299
- DisplayDuration: duration
300
- };
301
- MJGlobal.Instance.RaiseEvent({
302
- component: this,
303
- event: MJEventType.DisplaySimpleNotificationRequest,
304
- eventCode: "",
305
- args: data
306
- });
307
- }
308
- columnReorder(args) {
309
- return __awaiter(this, void 0, void 0, function* () {
310
- // Remove the column from the original position
311
- // need to find the column in the viewColumns array because args.old/new Indexes are from the visibleColumns array
312
- const fieldName = args.column.field;
313
- if (fieldName) {
314
- const vcOldIndex = this.viewColumns.findIndex((vc) => vc.Name === fieldName);
315
- const vcNewIndex = this.viewColumns.findIndex((vc) => vc.orderIndex === args.newIndex);
316
- if (vcOldIndex >= 0) {
317
- // got the index, now remove the element
318
- const element = this.viewColumns.splice(vcOldIndex, 1)[0];
319
- // Insert it at the new position
320
- this.viewColumns.splice(vcNewIndex, 0, element);
321
- // go through all of the columns and set orderIndex as that isn't done automatically
322
- let visColIndex = 0;
323
- for (let i = 0; i < this.viewColumns.length; i++) {
324
- if (!this.viewColumns[i].hidden) {
325
- this.viewColumns[i].orderIndex = visColIndex;
326
- visColIndex++;
327
- }
328
- }
329
- // 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
330
- for (let i = 0; i < this.viewColumns.length; i++) {
331
- if (this.viewColumns[i].hidden) {
332
- this.viewColumns[i].orderIndex = visColIndex;
333
- visColIndex++;
334
- }
335
- }
336
- // make sure that _newGridState.columnSettings is set
337
- this._newGridState.columnSettings = this.viewColumns;
338
- this._viewDirty = true;
339
- this.SaveView();
340
- }
341
- }
342
- });
343
- }
344
- columnResize(args) {
345
- return __awaiter(this, void 0, void 0, function* () {
346
- for (const col of args) {
347
- const c = col.column;
348
- const viewCol = this.viewColumns.find(vc => vc.Name === c.field);
349
- const visCol = this.visibleColumns.find(vc => vc.Name === c.field);
350
- const visCols = this.visibleColumns;
351
- if (viewCol)
352
- viewCol.width = col.newWidth;
353
- }
354
- this._newGridState.columnSettings = this.viewColumns.map(vc => {
355
- return {
356
- Name: vc.Name,
357
- DisplayName: vc.DisplayName,
358
- width: vc.width,
359
- orderIndex: vc.orderIndex,
360
- hidden: vc.hidden
361
- };
362
- });
363
- this._viewDirty = true;
364
- this.SaveView();
365
- });
366
- }
367
- sortChanged(sort) {
368
- return __awaiter(this, void 0, void 0, function* () {
369
- this._newGridState.sortSettings = sort;
370
- this.sortSettings = sort; // for the UI display - grid binding to this shows that the sort is applied via arrows in the column headers
371
- if (this.IsDynamicView()) {
372
- // Dynamic View, we have this.Params and can add an OrderBy and then just Refresh() the entire component
373
- // that will result in going to the server for a refreshed set of data
374
- if (this.Params) {
375
- this.Params.OrderBy = sort[0].field + ' ' + (sort[0].dir === 'asc' ? 'ASC' : 'DESC');
376
- this.Refresh(this.Params);
377
- }
378
- else {
379
- LogError("sortChanged() called but this.Params is null or undefined"); // should never get here
380
- }
381
- }
382
- else {
383
- // Saved view - we do this on the server side only
384
- this._viewDirty = true;
385
- this.innerSaveView(); // for sort changes we call innerSaveView() directly, not through SaveView() which is debounced
386
- }
387
- });
388
- }
389
- cellClickHandler(args) {
390
- return __awaiter(this, void 0, void 0, function* () {
391
- if (this.compareMode)
392
- return;
393
- if (this._entityInfo) {
394
- this.rowClicked.emit({
395
- entityId: this._entityInfo.ID,
396
- entityName: this._entityInfo.Name,
397
- recordId: args.dataItem.ID
398
- });
399
- if (this._entityInfo.AllowUpdateAPI &&
400
- this.EditMode !== "None") {
401
- const perm = this._entityInfo.GetUserPermisions(new Metadata().CurrentUser);
402
- if (perm.CanUpdate) {
403
- this.StartEditMode();
404
- args.sender.editCell(args.rowIndex, args.columnIndex, this.createFormGroup(args.dataItem));
405
- }
406
- }
407
- if (!this.InEditMode && this.AutoNavigate) {
408
- // tell app router to go to this record
409
- this.router.navigate(['resource', 'record', args.dataItem.ID], { queryParams: { Entity: this._entityInfo.Name } });
410
- }
411
- }
412
- });
413
- }
414
- createFormGroup(dataItem) {
415
- const groupFields = {};
416
- this.viewColumns.forEach((vc) => {
417
- if (vc.EntityField.AllowUpdateAPI &&
418
- vc.EntityField.IsVirtual === false &&
419
- vc.EntityField.AllowUpdateInView)
420
- groupFields[vc.Name] = dataItem[vc.Name];
421
- });
422
- return this.formBuilder.group(groupFields);
423
- }
424
- getEditor(ef) {
425
- switch (ef.TSType) {
426
- case EntityFieldTSType.Boolean:
427
- return "boolean";
428
- case EntityFieldTSType.Date:
429
- return "date";
430
- case EntityFieldTSType.Number:
431
- return "numeric";
432
- default:
433
- return "text";
434
- }
435
- }
436
- cellCloseHandler(args) {
437
- var _a;
438
- return __awaiter(this, void 0, void 0, function* () {
439
- try {
440
- if (this._entityInfo && this.EditMode !== "None") {
441
- const { formGroup, dataItem } = args;
442
- if (!formGroup.valid) {
443
- // prevent closing the edited cell if there are invalid values.
444
- args.preventDefault();
445
- }
446
- else if (formGroup.dirty) {
447
- if (args.originalEvent && args.originalEvent.keyCode === Keys.Escape)
448
- return; // user hit escape, so don't save their changes
449
- // update the data item with the new values - this drives UI refresh while we save the record...
450
- Object.assign(dataItem, formGroup.value);
451
- const md = new Metadata();
452
- let record;
453
- let bSaved = false;
454
- if (this.EditMode === "Save") {
455
- record = yield md.GetEntityObject(this._entityInfo.Name);
456
- yield record.Load(dataItem.ID);
457
- record.SetMany(formGroup.value);
458
- bSaved = yield record.Save();
459
- if (!bSaved)
460
- this.CreateSimpleNotification("Error saving record: " + record.ID, 'error', 5000);
461
- }
462
- else {
463
- record = (_a = this._pendingRecords.find((r) => r.record.ID === dataItem.ID)) === null || _a === void 0 ? void 0 : _a.record;
464
- if (!record) { // haven't edited this one before
465
- record = yield md.GetEntityObject(this._viewEntity.Get('Entity'));
466
- yield record.Load(dataItem.ID);
467
- this._pendingRecords.push({ record,
468
- row: args.rowIndex,
469
- dataItem }); // don't save - put the changed record on a queue for saving later by our container
470
- }
471
- // go through the formGroup and only set the values that exist as columns in the grid
472
- const keys = Object.keys(formGroup.value);
473
- keys.forEach((k) => {
474
- const vc = this.viewColumns.find((vc) => vc.Name === k && vc.hidden === false);
475
- if (vc) {
476
- record.Set(k, formGroup.value[k]);
477
- }
478
- });
479
- //record.SetMany(formGroup.value);
480
- }
481
- this.rowEdited.emit({
482
- record: record,
483
- row: args.rowIndex,
484
- saved: bSaved
485
- });
486
- }
487
- }
488
- }
489
- catch (e) {
490
- console.error(e);
491
- }
492
- finally {
493
- this.EndEditMode();
494
- }
495
- });
496
- }
497
- // this handles reverting pending cahnges to records WITHIN the grid, not the user view settings, unrelated to that.
498
- RevertPendingChanges() {
499
- if (this._pendingRecords && this._pendingRecords.length > 0) {
500
- this._pendingRecords.forEach((r) => {
501
- r.record.Revert();
502
- Object.assign(r.dataItem, r.record.GetAll()); // copy the original values back to the data Item which gets the grid to display the old values again...
503
- });
504
- this._pendingRecords = [];
505
- if (this.Params)
506
- this.Refresh(this.Params);
507
- }
508
- }
509
- ngOnInit() {
510
- }
511
- ngAfterViewInit() {
512
- //this.setGridHeight();
513
- if (this.Params)
514
- this.Refresh(this.Params);
515
- }
516
- ngOnDestroy() {
517
- if (this.resizeSub) {
518
- this.resizeSub.unsubscribe();
519
- }
520
- }
521
- ResizeGrid() {
522
- // doesn't do anything now, handled by mjFillContainer directive
523
- }
524
- get AllowLoad() {
525
- return this._allowLoad;
526
- }
527
- set AllowLoad(value) {
528
- this._allowLoad = value;
529
- if (value === true && this._deferLoadCount === 0) {
530
- this._deferLoadCount++; // only do this one time
531
- if (this.Params)
532
- this.Refresh(this.Params);
533
- return;
534
- }
535
- }
536
- RefreshFromSavedParams() {
537
- return __awaiter(this, void 0, void 0, function* () {
538
- if (this.Params)
539
- this.Refresh(this.Params);
540
- });
541
- }
542
- Refresh(params) {
543
- var _a;
544
- return __awaiter(this, void 0, void 0, function* () {
545
- this.Params = params;
546
- if (this.AllowLoad === false) {
547
- return;
548
- }
549
- if (params && (params.ViewEntity || params.ViewID || params.ViewName || (params.EntityName && params.ExtraFilter))) {
550
- const startTime = new Date().getTime();
551
- this.isLoading = true;
552
- const md = new Metadata();
553
- const rv = new RunView();
554
- // 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
555
- // this is done for performance purposes
556
- if (!params.ViewEntity && (params.ViewID || params.ViewName)) {
557
- if (params.ViewID && params.ViewID > 0) {
558
- this._viewEntity = (yield ViewInfo.GetViewEntity(params.ViewID));
559
- this._entityInfo = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Get('EntityID')); });
560
- }
561
- else if (params.ViewName) {
562
- this._viewEntity = (yield ViewInfo.GetViewEntityByName(params.ViewName));
563
- this._entityInfo = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Get('EntityID')); });
564
- }
565
- params.ViewEntity = this._viewEntity;
566
- }
567
- else
568
- this._viewEntity = params.ViewEntity; //passed in via params in the Refresh() function
569
- const rvResult = yield rv.RunView(params);
570
- if (!rvResult.Success) {
571
- // it failed
572
- this.CreateSimpleNotification("Error running view:\n\n" + rvResult.ErrorMessage, 'error', 5000);
573
- }
574
- else {
575
- // it worked
576
- this.viewData = rvResult.Results;
577
- this.totalRowCount = rvResult.TotalRowCount;
578
- this.formattedData = new Array(this.viewData.length);
579
- if (this._viewEntity) {
580
- // we were passed the view entity for efficiency, no need to load it again!
581
- this._entityInfo = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Get('EntityID')); });
582
- }
583
- else
584
- this._entityInfo = md.Entities.find(x => x.Name === params.EntityName);
585
- let cols;
586
- if (this._viewEntity)
587
- cols = this._viewEntity.Columns;
588
- else
589
- cols = (_a = this._entityInfo) === null || _a === void 0 ? void 0 : _a.Fields.filter((f) => f.DefaultInView).map((f) => {
590
- return {
591
- ID: f.ID,
592
- Name: f.Name,
593
- DisplayName: f.DisplayName,
594
- EntityField: f,
595
- hidden: false,
596
- orderIndex: f.Sequence,
597
- width: f.DefaultColumnWidth ? f.DefaultColumnWidth : 100,
598
- };
599
- });
600
- if (cols) {
601
- this.viewColumns = cols;
602
- const tempCols = cols.filter(x => x.hidden === false).sort((a, b) => {
603
- const aOrder = a.orderIndex != null ? a.orderIndex : 9999;
604
- const bOrder = b.orderIndex != null ? b.orderIndex : 9999;
605
- return aOrder - bOrder;
606
- });
607
- this.visibleColumns = tempCols;
608
- }
609
- // sorting setup
610
- if (this._viewEntity) {
611
- const temp = this._viewEntity.ViewSortInfo;
612
- const kendoSortSettings = temp.map((s) => { return { field: s.field, dir: s.direction === 1 ? 'asc' : 'desc' }; });
613
- this.sortSettings = kendoSortSettings;
614
- }
615
- this.skip = 0;
616
- this.virtualLoadData();
617
- }
618
- this.viewExecutionTime = (new Date().getTime() - startTime) / 1000; // in seconds
619
- this.isLoading = false;
620
- }
621
- else {
622
- LogError("Refresh(params) must have ViewID or ViewName or (EntityName and ExtraFilter)");
623
- }
624
- });
625
- }
626
- GetColumnTitle(col) {
627
- if (col.DisplayName)
628
- return col.DisplayName; // use view's display name first if it exists
629
- else if (col.EntityField.DisplayName)
630
- return col.EntityField.DisplayName; // then use entity display name, if that exist
631
- else
632
- return col.Name; // otherwise just use the column name
633
- }
634
- GetColumnCellStyle(col) {
635
- switch (col.EntityField.Type.trim().toLowerCase()) {
636
- case "money":
637
- case 'decimal':
638
- case 'real':
639
- case 'float':
640
- case 'int':
641
- return { 'text-align': 'right', 'vertical-align': 'top' }; // right align numbers,
642
- default:
643
- return { 'text-align': 'left', 'vertical-align': 'top' }; // left align everything else
644
- }
645
- }
646
- selectionChange(args) {
647
- var _a, _b, _c, _d;
648
- if (this.compareRecords.length && ((_a = args === null || args === void 0 ? void 0 : args.deselectedRows) === null || _a === void 0 ? void 0 : _a.length)) {
649
- const tempRow = (_b = args === null || args === void 0 ? void 0 : args.deselectedRows[0]) === null || _b === void 0 ? void 0 : _b.dataItem;
650
- this.compareRecords = this.compareRecords.filter(record => record.ID !== (tempRow === null || tempRow === void 0 ? void 0 : tempRow.ID));
651
- }
652
- else if ((_c = args === null || args === void 0 ? void 0 : args.selectedRows) === null || _c === void 0 ? void 0 : _c.length) {
653
- const tempRow = (_d = args === null || args === void 0 ? void 0 : args.selectedRows[0]) === null || _d === void 0 ? void 0 : _d.dataItem;
654
- this.compareRecords.push(tempRow);
655
- }
656
- }
657
- enableCompare(cancel = false) {
658
- if (!cancel && this.selectedKeys.length) {
659
- this.isDialogOpened = true;
660
- }
661
- this.compareMode = !this.compareMode;
662
- this.selectedKeys = [];
663
- }
664
- closeDialog() {
665
- this.isDialogOpened = false;
666
- this.compareRecords = [];
667
- }
668
- doExcelExport() {
669
- return __awaiter(this, void 0, void 0, function* () {
670
- if (this.kendoExcelExport === null)
671
- throw new Error("kendoExcelExport is null, cannot export data");
672
- try {
673
- this.CreateSimpleNotification("Working on the export, will notify you when it is complete...", 'info', 2000);
674
- const data = yield this.getExportData();
675
- // we have the data.
676
- const cols = this.viewColumns.filter((vc) => vc.hidden === false);
677
- this.exportColumns = cols;
678
- this.exportData = data;
679
- // before we call the save, we need to let Angular do its thing that will result in the kendoExcelExport component binding properly to
680
- // the exportColumns and exportData arrays. So we wait for the next tick before we call save()
681
- setTimeout(() => {
682
- this.kendoExcelExport.save();
683
- this.CreateSimpleNotification("Excel Export Complete", 'success', 2000);
684
- }, 100);
685
- }
686
- catch (e) {
687
- this.CreateSimpleNotification("Error exporting data", 'error', 5000);
688
- LogError(e);
689
- }
690
- });
691
- }
692
- getExportData() {
693
- return __awaiter(this, void 0, void 0, function* () {
694
- // Get the data for the ENTIRE view, not just the current page
695
- const md = new Metadata();
696
- const rv = new RunView();
697
- const p = Object.assign(Object.assign({}, this.Params), { IgnoreMaxRows: true, ForceAuditLog: true, AuditLogDescription: `Export of Data From ${this._viewEntity ? '"' + this._viewEntity.Get('Name') + '"' : ''} View for User ${md.CurrentUser.Email}` });
698
- const result = yield rv.RunView(p);
699
- if (result && result.Success) {
700
- return result.Results;
701
- }
702
- else
703
- throw new Error("Unable to get export data");
704
- });
705
- }
706
- }
707
- UserViewGridComponent.ɵfac = function UserViewGridComponent_Factory(t) { return new (t || UserViewGridComponent)(i0.ɵɵdirectiveInject(i1.FormBuilder), i0.ɵɵdirectiveInject(i2.Router)); };
708
- UserViewGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserViewGridComponent, selectors: [["mj-user-view-grid"]], viewQuery: function UserViewGridComponent_Query(rf, ctx) { if (rf & 1) {
709
- i0.ɵɵviewQuery(_c0, 5, GridComponent);
710
- i0.ɵɵviewQuery(_c0, 5, ElementRef);
711
- i0.ɵɵviewQuery(_c1, 5, ExcelExportComponent);
712
- } if (rf & 2) {
713
- let _t;
714
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElement = _t.first);
715
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElementRef = _t.first);
716
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoExcelExport = _t.first);
717
- } }, inputs: { Params: "Params", BottomMargin: "BottomMargin", InEditMode: "InEditMode", EditMode: "EditMode", AutoNavigate: "AutoNavigate", AllowLoad: "AllowLoad" }, outputs: { rowClicked: "rowClicked", rowEdited: "rowEdited" }, decls: 10, vars: 19, consts: [["mjFillContainer", "", 1, "user-view-grid-wrap"], ["mjFillContainer", "", "scrollable", "virtual", "kendoGridSelectBy", "", 3, "resizable", "data", "skip", "pageSize", "rowHeight", "loading", "height", "sortable", "sort", "reorderable", "selectable", "selectedKeys", "pageChange", "selectedKeysChange", "cellClick", "cellClose", "columnReorder", "columnResize", "selectionChange", "sortChange"], ["kendoGrid", ""], ["kendoGridToolbarTemplate", ""], [3, "width", "headerStyle", "style", 4, "ngIf"], [3, "field", "title", "width", "editable", "editor", "headerStyle", "style", 4, "ngFor", "ngForOf"], [3, "data", "fileName"], ["excelExport", ""], [3, "field", "title", 4, "ngFor", "ngForOf"], [4, "ngIf"], ["kendoButton", "", "icon", "file-excel", 3, "disabled", "click"], ["class", "k-button k-button-md k-rounded-md k-button-solid-base k-button-solid", 3, "click", 4, "ngIf"], [1, "k-button", "k-button-md", "k-rounded-md", "k-button-solid-base", "k-button-solid", 3, "disabled", "click"], ["kendoButton", "", "icon", "refresh", 3, "primary", "click", 4, "ngIf"], [1, "k-button", "k-button-md", "k-rounded-md", "k-button-solid-base", "k-button-solid", 3, "click"], ["kendoButton", "", "icon", "refresh", 3, "primary", "click"], [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, "width", "minHeight", "minWidth", "resizable", "close", 4, "ngIf"], ["title", "Compare Records", 3, "width", "minHeight", "minWidth", "resizable", "close"], [1, "k-d-flex", "k-flex-col", "k-justify-content-between", "k-h-full"], [3, "recordsToCompare", "visibleColumns"]], template: function UserViewGridComponent_Template(rf, ctx) { if (rf & 1) {
718
- i0.ɵɵelementStart(0, "div", 0)(1, "kendo-grid", 1, 2);
719
- i0.ɵɵlistener("pageChange", function UserViewGridComponent_Template_kendo_grid_pageChange_1_listener($event) { return ctx.pageChange($event); })("selectedKeysChange", function UserViewGridComponent_Template_kendo_grid_selectedKeysChange_1_listener($event) { return ctx.selectedKeys = $event; })("cellClick", function UserViewGridComponent_Template_kendo_grid_cellClick_1_listener($event) { return ctx.cellClickHandler($event); })("cellClose", function UserViewGridComponent_Template_kendo_grid_cellClose_1_listener($event) { return ctx.cellCloseHandler($event); })("columnReorder", function UserViewGridComponent_Template_kendo_grid_columnReorder_1_listener($event) { return ctx.columnReorder($event); })("columnResize", function UserViewGridComponent_Template_kendo_grid_columnResize_1_listener($event) { return ctx.columnResize($event); })("selectionChange", function UserViewGridComponent_Template_kendo_grid_selectionChange_1_listener($event) { return ctx.selectionChange($event); })("sortChange", function UserViewGridComponent_Template_kendo_grid_sortChange_1_listener($event) { return ctx.sortChanged($event); });
720
- i0.ɵɵtemplate(3, UserViewGridComponent_ng_template_3_Template, 6, 4, "ng-template", 3);
721
- i0.ɵɵtemplate(4, UserViewGridComponent_kendo_grid_checkbox_column_4_Template, 1, 6, "kendo-grid-checkbox-column", 4);
722
- i0.ɵɵtemplate(5, UserViewGridComponent_kendo_grid_column_5_Template, 2, 10, "kendo-grid-column", 5);
723
- i0.ɵɵelementStart(6, "kendo-excelexport", 6, 7);
724
- i0.ɵɵtemplate(8, UserViewGridComponent_kendo_excelexport_column_8_Template, 1, 2, "kendo-excelexport-column", 8);
725
- i0.ɵɵelementEnd()()();
726
- i0.ɵɵtemplate(9, UserViewGridComponent_div_9_Template, 3, 1, "div", 9);
727
- } if (rf & 2) {
728
- i0.ɵɵadvance(1);
729
- i0.ɵɵproperty("resizable", true)("data", ctx.gridView)("skip", ctx.skip)("pageSize", ctx.pageSize)("rowHeight", 36)("loading", ctx.isLoading)("height", ctx.gridHeight)("sortable", true)("sort", ctx.sortSettings)("resizable", true)("reorderable", true)("selectable", true)("selectedKeys", ctx.selectedKeys);
730
- i0.ɵɵadvance(3);
731
- i0.ɵɵproperty("ngIf", ctx.compareMode);
732
- i0.ɵɵadvance(1);
733
- i0.ɵɵproperty("ngForOf", ctx.visibleColumns);
734
- i0.ɵɵadvance(1);
735
- i0.ɵɵproperty("data", ctx.exportData)("fileName", (ctx._viewEntity ? ctx._viewEntity.Get("Name") : ctx._entityInfo == null ? null : ctx._entityInfo.Name) + ".xlsx");
736
- i0.ɵɵadvance(2);
737
- i0.ɵɵproperty("ngForOf", ctx.exportColumns);
738
- i0.ɵɵadvance(1);
739
- i0.ɵɵproperty("ngIf", ctx.isDialogOpened);
740
- } }, dependencies: [i3.NgForOf, i3.NgIf, i4.GridComponent, i4.ToolbarTemplateDirective, i4.SelectionDirective, i4.ColumnComponent, i4.FooterTemplateDirective, i4.CheckboxColumnComponent, i5.WindowComponent, i6.ExcelExportComponent, i6.ColumnComponent, i7.Button, i3.DecimalPipe], styles: [".user-view-grid-wrap[_ngcontent-%COMP%] {\r\n height: calc(100vh-20px);\r\n}\r\n\r\n.user-view-grid-column-header[_ngcontent-%COMP%] {\r\n background-color: #a9c2af;\r\n font-size: 20pt;\r\n font-weight: bold;\r\n}"] });
741
- (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserViewGridComponent, [{
742
- type: Component,
743
- args: [{ selector: 'mj-user-view-grid', template: "<div class=\"user-view-grid-wrap\" mjFillContainer>\r\n <kendo-grid #kendoGrid\r\n mjFillContainer\r\n [resizable]=\"true\"\r\n [data]=\"gridView\" \r\n [skip]=\"skip\"\r\n [pageSize]=\"pageSize\"\r\n scrollable=\"virtual\"\r\n [rowHeight]=\"36\"\r\n (pageChange)=\"pageChange($event)\"\r\n [loading]=\"isLoading\"\r\n [height]=\"gridHeight\"\r\n [sortable]=\"true\"\r\n [sort]=\"sortSettings\" \r\n [resizable]=\"true\"\r\n [reorderable]=\"true\"\r\n [selectable]=\"true\"\r\n kendoGridSelectBy\r\n [(selectedKeys)]=\"selectedKeys\"\r\n (cellClick)=\"cellClickHandler($event)\"\r\n (cellClose)=\"cellCloseHandler($event)\"\r\n (columnReorder)=\"columnReorder($event)\"\r\n (columnResize)=\"columnResize($event)\"\r\n (selectionChange)=\"selectionChange($event)\"\r\n (sortChange)=\"sortChanged($event)\"\r\n >\r\n <ng-template kendoGridToolbarTemplate>\r\n <button kendoButton icon=\"file-excel\" [disabled]=\"compareMode\" (click)=\"doExcelExport()\" >Export to Excel</button>\r\n <button (click)=\"enableCompare(true)\" *ngIf=\"compareMode\" class=\"k-button k-button-md k-rounded-md k-button-solid-base k-button-solid\">Cancel</button>\r\n <button (click)=\"enableCompare()\" [disabled]=\"compareMode && compareRecords.length < 2\" class=\"k-button k-button-md k-rounded-md k-button-solid-base k-button-solid\">Compare</button>\r\n <button\r\n kendoButton\r\n [primary]=\"true\"\r\n icon=\"refresh\"\r\n *ngIf=\"showRefreshButton\"\r\n (click)=\"RefreshFromSavedParams()\">\r\n Refresh\r\n </button>\r\n </ng-template>\r\n\r\n <kendo-grid-checkbox-column \r\n *ngIf=\"compareMode\" \r\n [width]=\"50\" \r\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': '#a9c2af' }\" \r\n [style]=\"{'text-align': 'center', 'vertical-align': 'center'}\">\r\n </kendo-grid-checkbox-column>\r\n \r\n <kendo-grid-column \r\n *ngFor=\"let item of visibleColumns\" \r\n [field]=\"item.Name\" \r\n [title]=\"GetColumnTitle(item)\"\r\n [width]=\"item.width ? item.width : 100\"\r\n [editable]=\"item.EntityField.AllowUpdateAPI\"\r\n [editor]=\"getEditor(item.EntityField)\"\r\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': '#a9c2af' }\"\r\n [style]=\"this.GetColumnCellStyle(item)\"\r\n >\r\n <ng-template *ngIf=\"item===visibleColumns[0]\" kendoGridFooterTemplate >\r\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>\r\n </ng-template>\r\n </kendo-grid-column>\r\n\r\n <kendo-excelexport #excelExport [data]=\"exportData\" [fileName]=\"(_viewEntity ? _viewEntity.Get('Name') : _entityInfo?.Name) + '.xlsx'\">\r\n <kendo-excelexport-column *ngFor=\"let exportCol of exportColumns\" [field]=\"exportCol.Name\" [title]=\"exportCol.Name\">\r\n </kendo-excelexport-column>\r\n </kendo-excelexport>\r\n </kendo-grid>\r\n</div>\r\n\r\n<div *ngIf=\"isDialogOpened\">\r\n <div class=\"k-overlay\"></div>\r\n <kendo-window\r\n [width]=\"900\"\r\n [minHeight]=\"300\"\r\n [minWidth]=\"400\"\r\n [resizable]=\"true\"\r\n (close)=\"closeDialog()\"\r\n title=\"Compare Records\"\r\n *ngIf=\"isDialogOpened\"\r\n >\r\n <div class=\"k-d-flex k-flex-col k-justify-content-between k-h-full\">\r\n <div>\r\n <mj-record-compare [recordsToCompare]=\"compareRecords\" [visibleColumns]=\"visibleColumns\" ></mj-record-compare>\r\n </div>\r\n </div>\r\n </kendo-window>\r\n</div>\r\n ", styles: [".user-view-grid-wrap {\r\n height: calc(100vh-20px);\r\n}\r\n\r\n.user-view-grid-column-header {\r\n background-color: #a9c2af;\r\n font-size: 20pt;\r\n font-weight: bold;\r\n}"] }]
744
- }], function () { return [{ type: i1.FormBuilder }, { type: i2.Router }]; }, { Params: [{
745
- type: Input
746
- }], BottomMargin: [{
747
- type: Input
748
- }], InEditMode: [{
749
- type: Input
750
- }], EditMode: [{
751
- type: Input
752
- }], AutoNavigate: [{
753
- type: Input
754
- }], rowClicked: [{
755
- type: Output
756
- }], rowEdited: [{
757
- type: Output
758
- }], kendoGridElement: [{
759
- type: ViewChild,
760
- args: ['kendoGrid', { read: GridComponent }]
761
- }], kendoGridElementRef: [{
762
- type: ViewChild,
763
- args: ['kendoGrid', { read: ElementRef }]
764
- }], kendoExcelExport: [{
765
- type: ViewChild,
766
- args: ['excelExport', { read: ExcelExportComponent }]
767
- }], AllowLoad: [{
768
- type: Input
769
- }] }); })();
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
+ import { Component, ViewChild, ElementRef, Output, EventEmitter, Input } from '@angular/core';
11
+ import { Metadata, RunView, EntityFieldTSType, LogError, ViewInfo } from '@memberjunction/core';
12
+ import { GridComponent } from "@progress/kendo-angular-grid";
13
+ import { Keys } from '@progress/kendo-angular-common';
14
+ import { Subject } from 'rxjs';
15
+ import { ExcelExportComponent } from '@progress/kendo-angular-excel-export';
16
+ import { MJEventType, MJGlobal } from '@memberjunction/global';
17
+ import * as i0 from "@angular/core";
18
+ import * as i1 from "@angular/forms";
19
+ import * as i2 from "@angular/router";
20
+ import * as i3 from "@angular/common";
21
+ import * as i4 from "@progress/kendo-angular-grid";
22
+ import * as i5 from "@progress/kendo-angular-dialog";
23
+ import * as i6 from "@progress/kendo-angular-excel-export";
24
+ import * as i7 from "@progress/kendo-angular-buttons";
25
+ const _c0 = ["kendoGrid"];
26
+ const _c1 = ["excelExport"];
27
+ function UserViewGridComponent_ng_template_3_button_2_Template(rf, ctx) { if (rf & 1) {
28
+ const _r10 = i0.ɵɵgetCurrentView();
29
+ i0.ɵɵelementStart(0, "button", 14);
30
+ i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_button_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r9 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r9.enableCompare(true)); });
31
+ i0.ɵɵtext(1, "Cancel");
32
+ i0.ɵɵelementEnd();
33
+ } }
34
+ function UserViewGridComponent_ng_template_3_button_5_Template(rf, ctx) { if (rf & 1) {
35
+ const _r12 = i0.ɵɵgetCurrentView();
36
+ i0.ɵɵelementStart(0, "button", 15);
37
+ i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_button_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r11 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r11.RefreshFromSavedParams()); });
38
+ i0.ɵɵtext(1, " Refresh ");
39
+ i0.ɵɵelementEnd();
40
+ } if (rf & 2) {
41
+ i0.ɵɵproperty("primary", true);
42
+ } }
43
+ function UserViewGridComponent_ng_template_3_Template(rf, ctx) { if (rf & 1) {
44
+ const _r14 = i0.ɵɵgetCurrentView();
45
+ i0.ɵɵelementStart(0, "button", 10);
46
+ i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r13 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r13.doExcelExport()); });
47
+ i0.ɵɵtext(1, "Export to Excel");
48
+ i0.ɵɵelementEnd();
49
+ i0.ɵɵtemplate(2, UserViewGridComponent_ng_template_3_button_2_Template, 2, 0, "button", 11);
50
+ i0.ɵɵelementStart(3, "button", 12);
51
+ i0.ɵɵlistener("click", function UserViewGridComponent_ng_template_3_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r14); const ctx_r15 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r15.enableCompare()); });
52
+ i0.ɵɵtext(4, "Compare");
53
+ i0.ɵɵelementEnd();
54
+ i0.ɵɵtemplate(5, UserViewGridComponent_ng_template_3_button_5_Template, 2, 1, "button", 13);
55
+ } if (rf & 2) {
56
+ const ctx_r1 = i0.ɵɵnextContext();
57
+ i0.ɵɵproperty("disabled", ctx_r1.compareMode);
58
+ i0.ɵɵadvance(2);
59
+ i0.ɵɵproperty("ngIf", ctx_r1.compareMode);
60
+ i0.ɵɵadvance(1);
61
+ i0.ɵɵproperty("disabled", ctx_r1.compareMode && ctx_r1.compareRecords.length < 2);
62
+ i0.ɵɵadvance(2);
63
+ i0.ɵɵproperty("ngIf", ctx_r1.showRefreshButton);
64
+ } }
65
+ const _c2 = function () { return { "text-align": "center", "vertical-align": "center" }; };
66
+ const _c3 = function () { return { "font-weight": "bold", "background-color": "#a9c2af" }; };
67
+ function UserViewGridComponent_kendo_grid_checkbox_column_4_Template(rf, ctx) { if (rf & 1) {
68
+ i0.ɵɵelement(0, "kendo-grid-checkbox-column", 16);
69
+ } if (rf & 2) {
70
+ i0.ɵɵstyleMap(i0.ɵɵpureFunction0(4, _c2));
71
+ i0.ɵɵproperty("width", 50)("headerStyle", i0.ɵɵpureFunction0(5, _c3));
72
+ } }
73
+ function UserViewGridComponent_kendo_grid_column_5_1_ng_template_0_Template(rf, ctx) { if (rf & 1) {
74
+ i0.ɵɵtext(0);
75
+ i0.ɵɵpipe(1, "number");
76
+ i0.ɵɵpipe(2, "number");
77
+ i0.ɵɵelement(3, "br");
78
+ i0.ɵɵelementStart(4, "span", 19);
79
+ i0.ɵɵtext(5);
80
+ i0.ɵɵpipe(6, "number");
81
+ i0.ɵɵelementEnd();
82
+ } if (rf & 2) {
83
+ const ctx_r18 = i0.ɵɵnextContext(3);
84
+ i0.ɵɵtextInterpolate2(" ", i0.ɵɵpipeBind1(1, 3, ctx_r18.viewData.length), "", ctx_r18.totalRowCount > ctx_r18.viewData.length ? " of " + i0.ɵɵpipeBind1(2, 5, ctx_r18.totalRowCount) : " rows", "");
85
+ i0.ɵɵadvance(5);
86
+ i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(6, 7, ctx_r18.viewExecutionTime, "1.2-2"), " seconds");
87
+ } }
88
+ function UserViewGridComponent_kendo_grid_column_5_1_Template(rf, ctx) { if (rf & 1) {
89
+ i0.ɵɵtemplate(0, UserViewGridComponent_kendo_grid_column_5_1_ng_template_0_Template, 7, 10, "ng-template", 18);
90
+ } }
91
+ function UserViewGridComponent_kendo_grid_column_5_Template(rf, ctx) { if (rf & 1) {
92
+ i0.ɵɵelementStart(0, "kendo-grid-column", 17);
93
+ i0.ɵɵtemplate(1, UserViewGridComponent_kendo_grid_column_5_1_Template, 1, 0, null, 9);
94
+ i0.ɵɵelementEnd();
95
+ } if (rf & 2) {
96
+ const item_r16 = ctx.$implicit;
97
+ const ctx_r3 = i0.ɵɵnextContext();
98
+ i0.ɵɵstyleMap(ctx_r3.GetColumnCellStyle(item_r16));
99
+ i0.ɵɵproperty("field", item_r16.Name)("title", ctx_r3.GetColumnTitle(item_r16))("width", item_r16.width ? item_r16.width : 100)("editable", item_r16.EntityField.AllowUpdateAPI)("editor", ctx_r3.getEditor(item_r16.EntityField))("headerStyle", i0.ɵɵpureFunction0(9, _c3));
100
+ i0.ɵɵadvance(1);
101
+ i0.ɵɵproperty("ngIf", item_r16 === ctx_r3.visibleColumns[0]);
102
+ } }
103
+ function UserViewGridComponent_kendo_excelexport_column_8_Template(rf, ctx) { if (rf & 1) {
104
+ i0.ɵɵelement(0, "kendo-excelexport-column", 20);
105
+ } if (rf & 2) {
106
+ const exportCol_r19 = ctx.$implicit;
107
+ i0.ɵɵproperty("field", exportCol_r19.Name)("title", exportCol_r19.Name);
108
+ } }
109
+ function UserViewGridComponent_div_9_kendo_window_2_Template(rf, ctx) { if (rf & 1) {
110
+ const _r22 = i0.ɵɵgetCurrentView();
111
+ i0.ɵɵelementStart(0, "kendo-window", 23);
112
+ i0.ɵɵlistener("close", function UserViewGridComponent_div_9_kendo_window_2_Template_kendo_window_close_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r21 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r21.closeDialog()); });
113
+ i0.ɵɵelementStart(1, "div", 24)(2, "div");
114
+ i0.ɵɵelement(3, "mj-record-compare", 25);
115
+ i0.ɵɵelementEnd()()();
116
+ } if (rf & 2) {
117
+ const ctx_r20 = i0.ɵɵnextContext(2);
118
+ i0.ɵɵproperty("width", 900)("minHeight", 300)("minWidth", 400)("resizable", true);
119
+ i0.ɵɵadvance(3);
120
+ i0.ɵɵproperty("recordsToCompare", ctx_r20.compareRecords)("visibleColumns", ctx_r20.visibleColumns);
121
+ } }
122
+ function UserViewGridComponent_div_9_Template(rf, ctx) { if (rf & 1) {
123
+ i0.ɵɵelementStart(0, "div");
124
+ i0.ɵɵelement(1, "div", 21);
125
+ i0.ɵɵtemplate(2, UserViewGridComponent_div_9_kendo_window_2_Template, 4, 6, "kendo-window", 22);
126
+ i0.ɵɵelementEnd();
127
+ } if (rf & 2) {
128
+ const ctx_r6 = i0.ɵɵnextContext();
129
+ i0.ɵɵadvance(2);
130
+ i0.ɵɵproperty("ngIf", ctx_r6.isDialogOpened);
131
+ } }
132
+ export class UserViewGridComponent {
133
+ get PendingRecords() {
134
+ return this._pendingRecords;
135
+ }
136
+ StartEditMode() {
137
+ this.InEditMode = true;
138
+ }
139
+ EndEditMode() {
140
+ this.InEditMode = false;
141
+ this.editModeEnded.next();
142
+ }
143
+ EditingComplete() {
144
+ if (this.InEditMode) {
145
+ // we need to wait for edit mode to end before we can return true
146
+ return new Promise((resolve, reject) => {
147
+ const subscription = this.editModeEnded.subscribe(() => {
148
+ resolve(true);
149
+ subscription.unsubscribe();
150
+ });
151
+ });
152
+ }
153
+ else
154
+ return Promise.resolve(true); // not in edit mode, so editing is complete!
155
+ }
156
+ IsDynamicView() {
157
+ return !this._viewEntity; // if we have a viewEntity it is a stored view
158
+ }
159
+ pageChange(event) {
160
+ this.skip = event.skip;
161
+ this.virtualLoadData();
162
+ }
163
+ virtualLoadData() {
164
+ // check to see if we have already formatted the slice of the data we need right now
165
+ // we are storing the formattted data in the formattedData array and it has same set
166
+ // of indexes as the viewData array (raw unformatted data). When we first get viewData
167
+ // from the server we create an array of the same length as viewData, but have nulls in all of the
168
+ // indexes. As we format each row of viewData we store the formatted row in the same index
169
+ // in the formattedData array. So if we have already formatted the data we need for the current
170
+ // page, we just use that data, otherwise we format the data we need for the current page
171
+ try {
172
+ // check to see if we have already formatted the data we need for the current page
173
+ for (let i = this.skip; (i < (this.skip + this.pageSize)) && (i < this.viewData.length); i++) {
174
+ if (!this.formattedData[i]) {
175
+ // we have not formatted this row yet, so format it
176
+ const r = this.viewColumns.map((c) => {
177
+ if (c && c.EntityField && this.viewData[i] && this.viewData[i][c.EntityField.Name]) {
178
+ if (!c.hidden && c.EntityField.Name !== 'ID') {
179
+ const ef = c.EntityField;
180
+ return { field: c.EntityField.Name, value: ef.FormatValue(this.viewData[i][c.EntityField.Name], undefined, undefined, 300) };
181
+ }
182
+ else
183
+ return { field: c.EntityField.Name, value: this.viewData[i][c.EntityField.Name] }; // hidden column, so just return the value, don't bother formatting
184
+ }
185
+ else
186
+ return { field: c.Name, value: null };
187
+ });
188
+ // now r is an array of {field: string, value: any} objects, so we need to convert it to an object
189
+ // with the field names as the keys and the values as the values
190
+ const row = {};
191
+ for (let j = 0; j < r.length; j++) {
192
+ if (r[j] && r[j].field && r[j].field.length > 0)
193
+ row[r[j].field] = r[j].value;
194
+ }
195
+ this.formattedData[i] = row;
196
+ }
197
+ }
198
+ // now that we have made sure current page of data is formatted, we can return it
199
+ this.gridView = {
200
+ data: this.formattedData.slice(this.skip, this.skip + this.pageSize),
201
+ total: this.viewData.length,
202
+ };
203
+ }
204
+ catch (e) {
205
+ LogError(e);
206
+ }
207
+ }
208
+ constructor(formBuilder, router) {
209
+ this.formBuilder = formBuilder;
210
+ this.router = router;
211
+ this.title = 'UserViewGrid';
212
+ this.BottomMargin = 0;
213
+ this.InEditMode = false;
214
+ this.EditMode = "None";
215
+ this.AutoNavigate = true;
216
+ this.rowClicked = new EventEmitter();
217
+ this.rowEdited = new EventEmitter();
218
+ this.kendoGridElement = null;
219
+ this.kendoGridElementRef = null;
220
+ this.kendoExcelExport = null;
221
+ this._pendingRecords = [];
222
+ this.viewData = [];
223
+ this.totalRowCount = 0;
224
+ this.formattedData = [];
225
+ this.viewColumns = [];
226
+ this.visibleColumns = [];
227
+ this.sortSettings = [];
228
+ this.entityRecord = null;
229
+ this.skip = 0;
230
+ this.pageSize = 40;
231
+ this.isLoading = false;
232
+ this.gridView = { data: [], total: 0 };
233
+ this.gridHeight = 750;
234
+ this._newGridState = {};
235
+ this.editModeEnded = new Subject();
236
+ this.compareMode = false;
237
+ this.compareRecords = [];
238
+ this.selectableSettings = {
239
+ enabled: false
240
+ };
241
+ this.selectedKeys = [];
242
+ this.isDialogOpened = false;
243
+ this.showRefreshButton = true;
244
+ this.viewExecutionTime = 0;
245
+ this._viewDirty = false;
246
+ this._deferLoadCount = 0;
247
+ this._allowLoad = true;
248
+ // Export Functionality
249
+ this.exportColumns = [];
250
+ this.exportData = [];
251
+ }
252
+ SaveView() {
253
+ // debounced outer function...
254
+ clearTimeout(this._saveTimeout);
255
+ this._saveTimeout = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
256
+ // when we actually call inner save view we do await
257
+ yield this.innerSaveView();
258
+ }), 5000); // 5 seconds delay
259
+ }
260
+ ;
261
+ innerSaveView() {
262
+ return __awaiter(this, void 0, void 0, function* () {
263
+ if (this._viewDirty) {
264
+ const md = new Metadata();
265
+ if (this._viewEntity &&
266
+ this._viewEntity.Get('UserID') === md.CurrentUser.ID) {
267
+ // this view is a saved view, AND it belongs to the current user
268
+ // update the grid state if we have settings updates for columns and/or sorts
269
+ const tempGridState = JSON.parse(this._viewEntity.Get('GridState'));
270
+ const tempColSettings = this._newGridState.columnSettings ? this._newGridState.columnSettings : tempGridState.columnSettings;
271
+ tempColSettings.forEach((col) => { col.DisplayName, col.ID, col.Name, col.hidden, col.orderIndex, col.width; }); // remove EntityFieldInfo from the column settings
272
+ tempGridState.columnSettings = tempColSettings;
273
+ tempGridState.sortSettings = this._newGridState.sortSettings ? this._newGridState.sortSettings : tempGridState.sortSettings;
274
+ // now stringify the grid state and save it
275
+ this._viewEntity.Set('GridState', JSON.stringify(tempGridState));
276
+ const newSortState = tempGridState.sortSettings.map((s) => { return { field: s.field, direction: s.dir === 'asc' ? 1 : 2 }; });
277
+ const oldSortState = JSON.parse(this._viewEntity.Get('SortState'));
278
+ this._viewEntity.Set('SortState', JSON.stringify(newSortState));
279
+ if (yield this._viewEntity.Save()) {
280
+ // check to see if sort state changed and if so, refresh the grid
281
+ if (JSON.stringify(newSortState) !== JSON.stringify(oldSortState)) {
282
+ if (this.Params) // makes sure we have params before we refresh
283
+ this.Refresh(this.Params);
284
+ }
285
+ this._viewDirty = false;
286
+ }
287
+ else {
288
+ this.CreateSimpleNotification('Unable to save view settings', 'error', 5000);
289
+ }
290
+ }
291
+ }
292
+ });
293
+ }
294
+ CreateSimpleNotification(message, style, duration) {
295
+ const data = {
296
+ message: message,
297
+ style: style,
298
+ DisplayDuration: duration
299
+ };
300
+ MJGlobal.Instance.RaiseEvent({
301
+ component: this,
302
+ event: MJEventType.DisplaySimpleNotificationRequest,
303
+ eventCode: "",
304
+ args: data
305
+ });
306
+ }
307
+ columnReorder(args) {
308
+ return __awaiter(this, void 0, void 0, function* () {
309
+ // Remove the column from the original position
310
+ // need to find the column in the viewColumns array because args.old/new Indexes are from the visibleColumns array
311
+ const fieldName = args.column.field;
312
+ if (fieldName) {
313
+ const vcOldIndex = this.viewColumns.findIndex((vc) => vc.Name === fieldName);
314
+ const vcNewIndex = this.viewColumns.findIndex((vc) => vc.orderIndex === args.newIndex);
315
+ if (vcOldIndex >= 0) {
316
+ // got the index, now remove the element
317
+ const element = this.viewColumns.splice(vcOldIndex, 1)[0];
318
+ // Insert it at the new position
319
+ this.viewColumns.splice(vcNewIndex, 0, element);
320
+ // go through all of the columns and set orderIndex as that isn't done automatically
321
+ let visColIndex = 0;
322
+ for (let i = 0; i < this.viewColumns.length; i++) {
323
+ if (!this.viewColumns[i].hidden) {
324
+ this.viewColumns[i].orderIndex = visColIndex;
325
+ visColIndex++;
326
+ }
327
+ }
328
+ // 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
329
+ for (let i = 0; i < this.viewColumns.length; i++) {
330
+ if (this.viewColumns[i].hidden) {
331
+ this.viewColumns[i].orderIndex = visColIndex;
332
+ visColIndex++;
333
+ }
334
+ }
335
+ // make sure that _newGridState.columnSettings is set
336
+ this._newGridState.columnSettings = this.viewColumns;
337
+ this._viewDirty = true;
338
+ this.SaveView();
339
+ }
340
+ }
341
+ });
342
+ }
343
+ columnResize(args) {
344
+ return __awaiter(this, void 0, void 0, function* () {
345
+ for (const col of args) {
346
+ const c = col.column;
347
+ const viewCol = this.viewColumns.find(vc => vc.Name === c.field);
348
+ const visCol = this.visibleColumns.find(vc => vc.Name === c.field);
349
+ const visCols = this.visibleColumns;
350
+ if (viewCol)
351
+ viewCol.width = col.newWidth;
352
+ }
353
+ this._newGridState.columnSettings = this.viewColumns.map(vc => {
354
+ return {
355
+ Name: vc.Name,
356
+ DisplayName: vc.DisplayName,
357
+ width: vc.width,
358
+ orderIndex: vc.orderIndex,
359
+ hidden: vc.hidden
360
+ };
361
+ });
362
+ this._viewDirty = true;
363
+ this.SaveView();
364
+ });
365
+ }
366
+ sortChanged(sort) {
367
+ return __awaiter(this, void 0, void 0, function* () {
368
+ this._newGridState.sortSettings = sort;
369
+ this.sortSettings = sort; // for the UI display - grid binding to this shows that the sort is applied via arrows in the column headers
370
+ if (this.IsDynamicView()) {
371
+ // Dynamic View, we have this.Params and can add an OrderBy and then just Refresh() the entire component
372
+ // that will result in going to the server for a refreshed set of data
373
+ if (this.Params) {
374
+ this.Params.OrderBy = sort[0].field + ' ' + (sort[0].dir === 'asc' ? 'ASC' : 'DESC');
375
+ this.Refresh(this.Params);
376
+ }
377
+ else {
378
+ LogError("sortChanged() called but this.Params is null or undefined"); // should never get here
379
+ }
380
+ }
381
+ else {
382
+ // Saved view - we do this on the server side only
383
+ this._viewDirty = true;
384
+ this.innerSaveView(); // for sort changes we call innerSaveView() directly, not through SaveView() which is debounced
385
+ }
386
+ });
387
+ }
388
+ cellClickHandler(args) {
389
+ return __awaiter(this, void 0, void 0, function* () {
390
+ if (this.compareMode)
391
+ return;
392
+ if (this._entityInfo) {
393
+ this.rowClicked.emit({
394
+ entityId: this._entityInfo.ID,
395
+ entityName: this._entityInfo.Name,
396
+ recordId: args.dataItem.ID
397
+ });
398
+ if (this._entityInfo.AllowUpdateAPI &&
399
+ this.EditMode !== "None") {
400
+ const perm = this._entityInfo.GetUserPermisions(new Metadata().CurrentUser);
401
+ if (perm.CanUpdate) {
402
+ this.StartEditMode();
403
+ args.sender.editCell(args.rowIndex, args.columnIndex, this.createFormGroup(args.dataItem));
404
+ }
405
+ }
406
+ if (!this.InEditMode && this.AutoNavigate) {
407
+ // tell app router to go to this record
408
+ this.router.navigate(['resource', 'record', args.dataItem.ID], { queryParams: { Entity: this._entityInfo.Name } });
409
+ }
410
+ }
411
+ });
412
+ }
413
+ createFormGroup(dataItem) {
414
+ const groupFields = {};
415
+ this.viewColumns.forEach((vc) => {
416
+ if (vc.EntityField.AllowUpdateAPI &&
417
+ vc.EntityField.IsVirtual === false &&
418
+ vc.EntityField.AllowUpdateInView)
419
+ groupFields[vc.Name] = dataItem[vc.Name];
420
+ });
421
+ return this.formBuilder.group(groupFields);
422
+ }
423
+ getEditor(ef) {
424
+ switch (ef.TSType) {
425
+ case EntityFieldTSType.Boolean:
426
+ return "boolean";
427
+ case EntityFieldTSType.Date:
428
+ return "date";
429
+ case EntityFieldTSType.Number:
430
+ return "numeric";
431
+ default:
432
+ return "text";
433
+ }
434
+ }
435
+ cellCloseHandler(args) {
436
+ var _a;
437
+ return __awaiter(this, void 0, void 0, function* () {
438
+ try {
439
+ if (this._entityInfo && this.EditMode !== "None") {
440
+ const { formGroup, dataItem } = args;
441
+ if (!formGroup.valid) {
442
+ // prevent closing the edited cell if there are invalid values.
443
+ args.preventDefault();
444
+ }
445
+ else if (formGroup.dirty) {
446
+ if (args.originalEvent && args.originalEvent.keyCode === Keys.Escape)
447
+ return; // user hit escape, so don't save their changes
448
+ // update the data item with the new values - this drives UI refresh while we save the record...
449
+ Object.assign(dataItem, formGroup.value);
450
+ const md = new Metadata();
451
+ let record;
452
+ let bSaved = false;
453
+ if (this.EditMode === "Save") {
454
+ record = yield md.GetEntityObject(this._entityInfo.Name);
455
+ yield record.Load(dataItem.ID);
456
+ record.SetMany(formGroup.value);
457
+ bSaved = yield record.Save();
458
+ if (!bSaved)
459
+ this.CreateSimpleNotification("Error saving record: " + record.ID, 'error', 5000);
460
+ }
461
+ else {
462
+ record = (_a = this._pendingRecords.find((r) => r.record.ID === dataItem.ID)) === null || _a === void 0 ? void 0 : _a.record;
463
+ if (!record) { // haven't edited this one before
464
+ record = yield md.GetEntityObject(this._viewEntity.Get('Entity'));
465
+ yield record.Load(dataItem.ID);
466
+ this._pendingRecords.push({ record,
467
+ row: args.rowIndex,
468
+ dataItem }); // don't save - put the changed record on a queue for saving later by our container
469
+ }
470
+ // go through the formGroup and only set the values that exist as columns in the grid
471
+ const keys = Object.keys(formGroup.value);
472
+ keys.forEach((k) => {
473
+ const vc = this.viewColumns.find((vc) => vc.Name === k && vc.hidden === false);
474
+ if (vc) {
475
+ record.Set(k, formGroup.value[k]);
476
+ }
477
+ });
478
+ //record.SetMany(formGroup.value);
479
+ }
480
+ this.rowEdited.emit({
481
+ record: record,
482
+ row: args.rowIndex,
483
+ saved: bSaved
484
+ });
485
+ }
486
+ }
487
+ }
488
+ catch (e) {
489
+ console.error(e);
490
+ }
491
+ finally {
492
+ this.EndEditMode();
493
+ }
494
+ });
495
+ }
496
+ // this handles reverting pending cahnges to records WITHIN the grid, not the user view settings, unrelated to that.
497
+ RevertPendingChanges() {
498
+ if (this._pendingRecords && this._pendingRecords.length > 0) {
499
+ this._pendingRecords.forEach((r) => {
500
+ r.record.Revert();
501
+ Object.assign(r.dataItem, r.record.GetAll()); // copy the original values back to the data Item which gets the grid to display the old values again...
502
+ });
503
+ this._pendingRecords = [];
504
+ if (this.Params)
505
+ this.Refresh(this.Params);
506
+ }
507
+ }
508
+ ngOnInit() {
509
+ }
510
+ ngAfterViewInit() {
511
+ //this.setGridHeight();
512
+ if (this.Params)
513
+ this.Refresh(this.Params);
514
+ }
515
+ get AllowLoad() {
516
+ return this._allowLoad;
517
+ }
518
+ set AllowLoad(value) {
519
+ this._allowLoad = value;
520
+ if (value === true && this._deferLoadCount === 0) {
521
+ this._deferLoadCount++; // only do this one time
522
+ if (this.Params)
523
+ this.Refresh(this.Params);
524
+ return;
525
+ }
526
+ }
527
+ RefreshFromSavedParams() {
528
+ return __awaiter(this, void 0, void 0, function* () {
529
+ if (this.Params)
530
+ this.Refresh(this.Params);
531
+ });
532
+ }
533
+ Refresh(params) {
534
+ var _a;
535
+ return __awaiter(this, void 0, void 0, function* () {
536
+ this.Params = params;
537
+ if (this.AllowLoad === false) {
538
+ return;
539
+ }
540
+ if (params && (params.ViewEntity || params.ViewID || params.ViewName || (params.EntityName && params.ExtraFilter))) {
541
+ const startTime = new Date().getTime();
542
+ this.isLoading = true;
543
+ const md = new Metadata();
544
+ const rv = new RunView();
545
+ // 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
546
+ // this is done for performance purposes
547
+ if (!params.ViewEntity && (params.ViewID || params.ViewName)) {
548
+ if (params.ViewID && params.ViewID > 0) {
549
+ this._viewEntity = (yield ViewInfo.GetViewEntity(params.ViewID));
550
+ this._entityInfo = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Get('EntityID')); });
551
+ }
552
+ else if (params.ViewName) {
553
+ this._viewEntity = (yield ViewInfo.GetViewEntityByName(params.ViewName));
554
+ this._entityInfo = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Get('EntityID')); });
555
+ }
556
+ params.ViewEntity = this._viewEntity;
557
+ }
558
+ else
559
+ this._viewEntity = params.ViewEntity; //passed in via params in the Refresh() function
560
+ const rvResult = yield rv.RunView(params);
561
+ if (!rvResult.Success) {
562
+ // it failed
563
+ this.CreateSimpleNotification("Error running view:\n\n" + rvResult.ErrorMessage, 'error', 5000);
564
+ }
565
+ else {
566
+ // it worked
567
+ this.viewData = rvResult.Results;
568
+ this.totalRowCount = rvResult.TotalRowCount;
569
+ this.formattedData = new Array(this.viewData.length);
570
+ if (this._viewEntity) {
571
+ // we were passed the view entity for efficiency, no need to load it again!
572
+ this._entityInfo = md.Entities.find(x => { var _a; return x.ID === ((_a = this._viewEntity) === null || _a === void 0 ? void 0 : _a.Get('EntityID')); });
573
+ }
574
+ else
575
+ this._entityInfo = md.Entities.find(x => x.Name === params.EntityName);
576
+ let cols;
577
+ if (this._viewEntity)
578
+ cols = this._viewEntity.Columns;
579
+ else
580
+ cols = (_a = this._entityInfo) === null || _a === void 0 ? void 0 : _a.Fields.filter((f) => f.DefaultInView).map((f) => {
581
+ return {
582
+ ID: f.ID,
583
+ Name: f.Name,
584
+ DisplayName: f.DisplayName,
585
+ EntityField: f,
586
+ hidden: false,
587
+ orderIndex: f.Sequence,
588
+ width: f.DefaultColumnWidth ? f.DefaultColumnWidth : 100,
589
+ };
590
+ });
591
+ if (cols) {
592
+ this.viewColumns = cols;
593
+ const tempCols = cols.filter(x => x.hidden === false).sort((a, b) => {
594
+ const aOrder = a.orderIndex != null ? a.orderIndex : 9999;
595
+ const bOrder = b.orderIndex != null ? b.orderIndex : 9999;
596
+ return aOrder - bOrder;
597
+ });
598
+ this.visibleColumns = tempCols;
599
+ }
600
+ // sorting setup
601
+ if (this._viewEntity) {
602
+ const temp = this._viewEntity.ViewSortInfo;
603
+ const kendoSortSettings = temp.map((s) => { return { field: s.field, dir: s.direction === 1 ? 'asc' : 'desc' }; });
604
+ this.sortSettings = kendoSortSettings;
605
+ }
606
+ this.skip = 0;
607
+ this.virtualLoadData();
608
+ }
609
+ this.viewExecutionTime = (new Date().getTime() - startTime) / 1000; // in seconds
610
+ this.isLoading = false;
611
+ }
612
+ else {
613
+ LogError("Refresh(params) must have ViewID or ViewName or (EntityName and ExtraFilter)");
614
+ }
615
+ });
616
+ }
617
+ GetColumnTitle(col) {
618
+ if (col.DisplayName)
619
+ return col.DisplayName; // use view's display name first if it exists
620
+ else if (col.EntityField.DisplayName)
621
+ return col.EntityField.DisplayName; // then use entity display name, if that exist
622
+ else
623
+ return col.Name; // otherwise just use the column name
624
+ }
625
+ GetColumnCellStyle(col) {
626
+ switch (col.EntityField.Type.trim().toLowerCase()) {
627
+ case "money":
628
+ case 'decimal':
629
+ case 'real':
630
+ case 'float':
631
+ case 'int':
632
+ return { 'text-align': 'right', 'vertical-align': 'top' }; // right align numbers,
633
+ default:
634
+ return { 'text-align': 'left', 'vertical-align': 'top' }; // left align everything else
635
+ }
636
+ }
637
+ selectionChange(args) {
638
+ var _a, _b, _c, _d;
639
+ if (this.compareRecords.length && ((_a = args === null || args === void 0 ? void 0 : args.deselectedRows) === null || _a === void 0 ? void 0 : _a.length)) {
640
+ const tempRow = (_b = args === null || args === void 0 ? void 0 : args.deselectedRows[0]) === null || _b === void 0 ? void 0 : _b.dataItem;
641
+ this.compareRecords = this.compareRecords.filter(record => record.ID !== (tempRow === null || tempRow === void 0 ? void 0 : tempRow.ID));
642
+ }
643
+ else if ((_c = args === null || args === void 0 ? void 0 : args.selectedRows) === null || _c === void 0 ? void 0 : _c.length) {
644
+ const tempRow = (_d = args === null || args === void 0 ? void 0 : args.selectedRows[0]) === null || _d === void 0 ? void 0 : _d.dataItem;
645
+ this.compareRecords.push(tempRow);
646
+ }
647
+ }
648
+ enableCompare(cancel = false) {
649
+ if (!cancel && this.selectedKeys.length) {
650
+ this.isDialogOpened = true;
651
+ }
652
+ this.compareMode = !this.compareMode;
653
+ this.selectedKeys = [];
654
+ }
655
+ closeDialog() {
656
+ this.isDialogOpened = false;
657
+ this.compareRecords = [];
658
+ }
659
+ doExcelExport() {
660
+ return __awaiter(this, void 0, void 0, function* () {
661
+ if (this.kendoExcelExport === null)
662
+ throw new Error("kendoExcelExport is null, cannot export data");
663
+ try {
664
+ this.CreateSimpleNotification("Working on the export, will notify you when it is complete...", 'info', 2000);
665
+ const data = yield this.getExportData();
666
+ // we have the data.
667
+ const cols = this.viewColumns.filter((vc) => vc.hidden === false);
668
+ this.exportColumns = cols;
669
+ this.exportData = data;
670
+ // before we call the save, we need to let Angular do its thing that will result in the kendoExcelExport component binding properly to
671
+ // the exportColumns and exportData arrays. So we wait for the next tick before we call save()
672
+ setTimeout(() => {
673
+ this.kendoExcelExport.save();
674
+ this.CreateSimpleNotification("Excel Export Complete", 'success', 2000);
675
+ }, 100);
676
+ }
677
+ catch (e) {
678
+ this.CreateSimpleNotification("Error exporting data", 'error', 5000);
679
+ LogError(e);
680
+ }
681
+ });
682
+ }
683
+ getExportData() {
684
+ return __awaiter(this, void 0, void 0, function* () {
685
+ // Get the data for the ENTIRE view, not just the current page
686
+ const md = new Metadata();
687
+ const rv = new RunView();
688
+ const p = Object.assign(Object.assign({}, this.Params), { IgnoreMaxRows: true, ForceAuditLog: true, AuditLogDescription: `Export of Data From ${this._viewEntity ? '"' + this._viewEntity.Get('Name') + '"' : ''} View for User ${md.CurrentUser.Email}` });
689
+ const result = yield rv.RunView(p);
690
+ if (result && result.Success) {
691
+ return result.Results;
692
+ }
693
+ else
694
+ throw new Error("Unable to get export data");
695
+ });
696
+ }
697
+ }
698
+ UserViewGridComponent.ɵfac = function UserViewGridComponent_Factory(t) { return new (t || UserViewGridComponent)(i0.ɵɵdirectiveInject(i1.FormBuilder), i0.ɵɵdirectiveInject(i2.Router)); };
699
+ UserViewGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserViewGridComponent, selectors: [["mj-user-view-grid"]], viewQuery: function UserViewGridComponent_Query(rf, ctx) { if (rf & 1) {
700
+ i0.ɵɵviewQuery(_c0, 5, GridComponent);
701
+ i0.ɵɵviewQuery(_c0, 5, ElementRef);
702
+ i0.ɵɵviewQuery(_c1, 5, ExcelExportComponent);
703
+ } if (rf & 2) {
704
+ let _t;
705
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElement = _t.first);
706
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoGridElementRef = _t.first);
707
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.kendoExcelExport = _t.first);
708
+ } }, inputs: { Params: "Params", BottomMargin: "BottomMargin", InEditMode: "InEditMode", EditMode: "EditMode", AutoNavigate: "AutoNavigate", AllowLoad: "AllowLoad" }, outputs: { rowClicked: "rowClicked", rowEdited: "rowEdited" }, decls: 10, vars: 19, consts: [["mjFillContainer", "", 1, "user-view-grid-wrap"], ["mjFillContainer", "", "scrollable", "virtual", "kendoGridSelectBy", "", 3, "resizable", "data", "skip", "pageSize", "rowHeight", "loading", "height", "sortable", "sort", "reorderable", "selectable", "selectedKeys", "pageChange", "selectedKeysChange", "cellClick", "cellClose", "columnReorder", "columnResize", "selectionChange", "sortChange"], ["kendoGrid", ""], ["kendoGridToolbarTemplate", ""], [3, "width", "headerStyle", "style", 4, "ngIf"], [3, "field", "title", "width", "editable", "editor", "headerStyle", "style", 4, "ngFor", "ngForOf"], [3, "data", "fileName"], ["excelExport", ""], [3, "field", "title", 4, "ngFor", "ngForOf"], [4, "ngIf"], ["kendoButton", "", "icon", "file-excel", 3, "disabled", "click"], ["class", "k-button k-button-md k-rounded-md k-button-solid-base k-button-solid", 3, "click", 4, "ngIf"], [1, "k-button", "k-button-md", "k-rounded-md", "k-button-solid-base", "k-button-solid", 3, "disabled", "click"], ["kendoButton", "", "icon", "refresh", 3, "primary", "click", 4, "ngIf"], [1, "k-button", "k-button-md", "k-rounded-md", "k-button-solid-base", "k-button-solid", 3, "click"], ["kendoButton", "", "icon", "refresh", 3, "primary", "click"], [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, "width", "minHeight", "minWidth", "resizable", "close", 4, "ngIf"], ["title", "Compare Records", 3, "width", "minHeight", "minWidth", "resizable", "close"], [1, "k-d-flex", "k-flex-col", "k-justify-content-between", "k-h-full"], [3, "recordsToCompare", "visibleColumns"]], template: function UserViewGridComponent_Template(rf, ctx) { if (rf & 1) {
709
+ i0.ɵɵelementStart(0, "div", 0)(1, "kendo-grid", 1, 2);
710
+ i0.ɵɵlistener("pageChange", function UserViewGridComponent_Template_kendo_grid_pageChange_1_listener($event) { return ctx.pageChange($event); })("selectedKeysChange", function UserViewGridComponent_Template_kendo_grid_selectedKeysChange_1_listener($event) { return ctx.selectedKeys = $event; })("cellClick", function UserViewGridComponent_Template_kendo_grid_cellClick_1_listener($event) { return ctx.cellClickHandler($event); })("cellClose", function UserViewGridComponent_Template_kendo_grid_cellClose_1_listener($event) { return ctx.cellCloseHandler($event); })("columnReorder", function UserViewGridComponent_Template_kendo_grid_columnReorder_1_listener($event) { return ctx.columnReorder($event); })("columnResize", function UserViewGridComponent_Template_kendo_grid_columnResize_1_listener($event) { return ctx.columnResize($event); })("selectionChange", function UserViewGridComponent_Template_kendo_grid_selectionChange_1_listener($event) { return ctx.selectionChange($event); })("sortChange", function UserViewGridComponent_Template_kendo_grid_sortChange_1_listener($event) { return ctx.sortChanged($event); });
711
+ i0.ɵɵtemplate(3, UserViewGridComponent_ng_template_3_Template, 6, 4, "ng-template", 3);
712
+ i0.ɵɵtemplate(4, UserViewGridComponent_kendo_grid_checkbox_column_4_Template, 1, 6, "kendo-grid-checkbox-column", 4);
713
+ i0.ɵɵtemplate(5, UserViewGridComponent_kendo_grid_column_5_Template, 2, 10, "kendo-grid-column", 5);
714
+ i0.ɵɵelementStart(6, "kendo-excelexport", 6, 7);
715
+ i0.ɵɵtemplate(8, UserViewGridComponent_kendo_excelexport_column_8_Template, 1, 2, "kendo-excelexport-column", 8);
716
+ i0.ɵɵelementEnd()()();
717
+ i0.ɵɵtemplate(9, UserViewGridComponent_div_9_Template, 3, 1, "div", 9);
718
+ } if (rf & 2) {
719
+ i0.ɵɵadvance(1);
720
+ i0.ɵɵproperty("resizable", true)("data", ctx.gridView)("skip", ctx.skip)("pageSize", ctx.pageSize)("rowHeight", 36)("loading", ctx.isLoading)("height", ctx.gridHeight)("sortable", true)("sort", ctx.sortSettings)("resizable", true)("reorderable", true)("selectable", true)("selectedKeys", ctx.selectedKeys);
721
+ i0.ɵɵadvance(3);
722
+ i0.ɵɵproperty("ngIf", ctx.compareMode);
723
+ i0.ɵɵadvance(1);
724
+ i0.ɵɵproperty("ngForOf", ctx.visibleColumns);
725
+ i0.ɵɵadvance(1);
726
+ i0.ɵɵproperty("data", ctx.exportData)("fileName", (ctx._viewEntity ? ctx._viewEntity.Get("Name") : ctx._entityInfo == null ? null : ctx._entityInfo.Name) + ".xlsx");
727
+ i0.ɵɵadvance(2);
728
+ i0.ɵɵproperty("ngForOf", ctx.exportColumns);
729
+ i0.ɵɵadvance(1);
730
+ i0.ɵɵproperty("ngIf", ctx.isDialogOpened);
731
+ } }, dependencies: [i3.NgForOf, i3.NgIf, i4.GridComponent, i4.ToolbarTemplateDirective, i4.SelectionDirective, i4.ColumnComponent, i4.FooterTemplateDirective, i4.CheckboxColumnComponent, i5.WindowComponent, i6.ExcelExportComponent, i6.ColumnComponent, i7.Button, i3.DecimalPipe], styles: [".user-view-grid-wrap[_ngcontent-%COMP%] {\r\n height: calc(100vh-20px);\r\n}\r\n\r\n.user-view-grid-column-header[_ngcontent-%COMP%] {\r\n background-color: #a9c2af;\r\n font-size: 20pt;\r\n font-weight: bold;\r\n}"] });
732
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserViewGridComponent, [{
733
+ type: Component,
734
+ args: [{ selector: 'mj-user-view-grid', template: "<div class=\"user-view-grid-wrap\" mjFillContainer>\r\n <kendo-grid #kendoGrid\r\n mjFillContainer\r\n [resizable]=\"true\"\r\n [data]=\"gridView\" \r\n [skip]=\"skip\"\r\n [pageSize]=\"pageSize\"\r\n scrollable=\"virtual\"\r\n [rowHeight]=\"36\"\r\n (pageChange)=\"pageChange($event)\"\r\n [loading]=\"isLoading\"\r\n [height]=\"gridHeight\"\r\n [sortable]=\"true\"\r\n [sort]=\"sortSettings\" \r\n [resizable]=\"true\"\r\n [reorderable]=\"true\"\r\n [selectable]=\"true\"\r\n kendoGridSelectBy\r\n [(selectedKeys)]=\"selectedKeys\"\r\n (cellClick)=\"cellClickHandler($event)\"\r\n (cellClose)=\"cellCloseHandler($event)\"\r\n (columnReorder)=\"columnReorder($event)\"\r\n (columnResize)=\"columnResize($event)\"\r\n (selectionChange)=\"selectionChange($event)\"\r\n (sortChange)=\"sortChanged($event)\"\r\n >\r\n <ng-template kendoGridToolbarTemplate>\r\n <button kendoButton icon=\"file-excel\" [disabled]=\"compareMode\" (click)=\"doExcelExport()\" >Export to Excel</button>\r\n <button (click)=\"enableCompare(true)\" *ngIf=\"compareMode\" class=\"k-button k-button-md k-rounded-md k-button-solid-base k-button-solid\">Cancel</button>\r\n <button (click)=\"enableCompare()\" [disabled]=\"compareMode && compareRecords.length < 2\" class=\"k-button k-button-md k-rounded-md k-button-solid-base k-button-solid\">Compare</button>\r\n <button\r\n kendoButton\r\n [primary]=\"true\"\r\n icon=\"refresh\"\r\n *ngIf=\"showRefreshButton\"\r\n (click)=\"RefreshFromSavedParams()\">\r\n Refresh\r\n </button>\r\n </ng-template>\r\n\r\n <kendo-grid-checkbox-column \r\n *ngIf=\"compareMode\" \r\n [width]=\"50\" \r\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': '#a9c2af' }\" \r\n [style]=\"{'text-align': 'center', 'vertical-align': 'center'}\">\r\n </kendo-grid-checkbox-column>\r\n \r\n <kendo-grid-column \r\n *ngFor=\"let item of visibleColumns\" \r\n [field]=\"item.Name\" \r\n [title]=\"GetColumnTitle(item)\"\r\n [width]=\"item.width ? item.width : 100\"\r\n [editable]=\"item.EntityField.AllowUpdateAPI\"\r\n [editor]=\"getEditor(item.EntityField)\"\r\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': '#a9c2af' }\"\r\n [style]=\"this.GetColumnCellStyle(item)\"\r\n >\r\n <ng-template *ngIf=\"item===visibleColumns[0]\" kendoGridFooterTemplate >\r\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>\r\n </ng-template>\r\n </kendo-grid-column>\r\n\r\n <kendo-excelexport #excelExport [data]=\"exportData\" [fileName]=\"(_viewEntity ? _viewEntity.Get('Name') : _entityInfo?.Name) + '.xlsx'\">\r\n <kendo-excelexport-column *ngFor=\"let exportCol of exportColumns\" [field]=\"exportCol.Name\" [title]=\"exportCol.Name\">\r\n </kendo-excelexport-column>\r\n </kendo-excelexport>\r\n </kendo-grid>\r\n</div>\r\n\r\n<div *ngIf=\"isDialogOpened\">\r\n <div class=\"k-overlay\"></div>\r\n <kendo-window\r\n [width]=\"900\"\r\n [minHeight]=\"300\"\r\n [minWidth]=\"400\"\r\n [resizable]=\"true\"\r\n (close)=\"closeDialog()\"\r\n title=\"Compare Records\"\r\n *ngIf=\"isDialogOpened\"\r\n >\r\n <div class=\"k-d-flex k-flex-col k-justify-content-between k-h-full\">\r\n <div>\r\n <mj-record-compare [recordsToCompare]=\"compareRecords\" [visibleColumns]=\"visibleColumns\" ></mj-record-compare>\r\n </div>\r\n </div>\r\n </kendo-window>\r\n</div>\r\n ", styles: [".user-view-grid-wrap {\r\n height: calc(100vh-20px);\r\n}\r\n\r\n.user-view-grid-column-header {\r\n background-color: #a9c2af;\r\n font-size: 20pt;\r\n font-weight: bold;\r\n}"] }]
735
+ }], function () { return [{ type: i1.FormBuilder }, { type: i2.Router }]; }, { Params: [{
736
+ type: Input
737
+ }], BottomMargin: [{
738
+ type: Input
739
+ }], InEditMode: [{
740
+ type: Input
741
+ }], EditMode: [{
742
+ type: Input
743
+ }], AutoNavigate: [{
744
+ type: Input
745
+ }], rowClicked: [{
746
+ type: Output
747
+ }], rowEdited: [{
748
+ type: Output
749
+ }], kendoGridElement: [{
750
+ type: ViewChild,
751
+ args: ['kendoGrid', { read: GridComponent }]
752
+ }], kendoGridElementRef: [{
753
+ type: ViewChild,
754
+ args: ['kendoGrid', { read: ElementRef }]
755
+ }], kendoExcelExport: [{
756
+ type: ViewChild,
757
+ args: ['excelExport', { read: ExcelExportComponent }]
758
+ }], AllowLoad: [{
759
+ type: Input
760
+ }] }); })();