@memberjunction/ng-explorer-core 6.2.0-edge.5 → 6.2.0-edge.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +7 -2
  2. package/dist/app-routing.module.d.ts.map +1 -1
  3. package/dist/app-routing.module.js +12 -4
  4. package/dist/app-routing.module.js.map +1 -1
  5. package/dist/generated/lazy-feature-config.d.ts +1 -1
  6. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  7. package/dist/generated/lazy-feature-config.js +4 -2
  8. package/dist/generated/lazy-feature-config.js.map +1 -1
  9. package/dist/lib/resource-wrappers/record-form-mode.d.ts +44 -0
  10. package/dist/lib/resource-wrappers/record-form-mode.d.ts.map +1 -0
  11. package/dist/lib/resource-wrappers/record-form-mode.js +47 -0
  12. package/dist/lib/resource-wrappers/record-form-mode.js.map +1 -0
  13. package/dist/lib/resource-wrappers/record-resource.component.d.ts +56 -1
  14. package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
  15. package/dist/lib/resource-wrappers/record-resource.component.js +124 -9
  16. package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
  17. package/dist/lib/resource-wrappers/standard-form-create.d.ts +4 -0
  18. package/dist/lib/resource-wrappers/standard-form-create.d.ts.map +1 -0
  19. package/dist/lib/resource-wrappers/standard-form-create.js +6 -0
  20. package/dist/lib/resource-wrappers/standard-form-create.js.map +1 -0
  21. package/dist/lib/resource-wrappers/view-resource.component.d.ts +18 -1
  22. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  23. package/dist/lib/resource-wrappers/view-resource.component.js +105 -39
  24. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  25. package/dist/lib/shell/components/record-open/record-origin-crumb.component.d.ts.map +1 -1
  26. package/dist/lib/shell/components/record-open/record-origin-crumb.component.js +12 -8
  27. package/dist/lib/shell/components/record-open/record-origin-crumb.component.js.map +1 -1
  28. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +6 -0
  29. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
  30. package/dist/lib/shell/components/tabs/component-cache-manager.js +18 -3
  31. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
  32. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +2 -0
  33. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  34. package/dist/lib/shell/components/tabs/tab-container.component.js +38 -10
  35. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  36. package/dist/lib/shell/shell-chrome-policy.d.ts +6 -0
  37. package/dist/lib/shell/shell-chrome-policy.d.ts.map +1 -1
  38. package/dist/lib/shell/shell-chrome-policy.js +1 -0
  39. package/dist/lib/shell/shell-chrome-policy.js.map +1 -1
  40. package/dist/lib/shell/shell.component.d.ts +23 -0
  41. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  42. package/dist/lib/shell/shell.component.js +283 -71
  43. package/dist/lib/shell/shell.component.js.map +1 -1
  44. package/dist/lib/single-record/single-record.component.d.ts +27 -2
  45. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  46. package/dist/lib/single-record/single-record.component.js +54 -8
  47. package/dist/lib/single-record/single-record.component.js.map +1 -1
  48. package/dist/lib/user-notifications/user-notifications.component.d.ts +10 -2
  49. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  50. package/dist/lib/user-notifications/user-notifications.component.js +77 -22
  51. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  52. package/package.json +57 -57
@@ -4,19 +4,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component, ViewChild } from '@angular/core';
8
- import { BaseResourceComponent } from '@memberjunction/ng-shared';
7
+ import { Component, ViewChild, inject } from '@angular/core';
8
+ import { BaseResourceComponent, SafeDetectChanges } from '@memberjunction/ng-shared';
9
9
  import { ViewInfo } from '@memberjunction/core-entities';
10
10
  import { RegisterClass, MJGlobal, MJEventType, UUIDsEqual } from '@memberjunction/global';
11
- import { CompositeKey, BaseEntity } from '@memberjunction/core';
11
+ import { CompositeKey, BaseEntity, LogError } from '@memberjunction/core';
12
+ import { FormResolverService } from '@memberjunction/ng-base-forms';
12
13
  import { ExportColumnTypeForSQLType } from '@memberjunction/ng-entity-viewer';
13
14
  import { GraphQLListsClient } from '@memberjunction/graphql-dataprovider';
15
+ import { ShouldOfferStandardFormCreate } from './standard-form-create';
14
16
  import { debounceTime, filter, takeUntil } from 'rxjs/operators';
15
17
  import * as i0 from "@angular/core";
16
18
  import * as i1 from "@memberjunction/ng-export-service";
17
19
  import * as i2 from "@memberjunction/ng-shared-generic";
18
20
  import * as i3 from "@memberjunction/ng-entity-viewer";
19
21
  import * as i4 from "@memberjunction/ng-list-management";
22
+ import * as i5 from "@memberjunction/ng-ui-components";
20
23
  const _c0 = ["container"];
21
24
  const _c1 = ["entityViewer"];
22
25
  function UserViewResource_Conditional_2_Template(rf, ctx) { if (rf & 1) {
@@ -44,17 +47,29 @@ function UserViewResource_Conditional_4_Conditional_4_Template(rf, ctx) { if (rf
44
47
  i0.ɵɵadvance();
45
48
  i0.ɵɵtextInterpolate(ctx_r0.viewEntity.Description);
46
49
  } }
47
- function UserViewResource_Conditional_4_Conditional_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
48
- i0.ɵɵelement(0, "i", 19);
49
- } }
50
- function UserViewResource_Conditional_4_Conditional_10_Conditional_2_Template(rf, ctx) { if (rf & 1) {
51
- i0.ɵɵelement(0, "i", 20);
52
- } }
53
50
  function UserViewResource_Conditional_4_Conditional_10_Template(rf, ctx) { if (rf & 1) {
54
51
  const _r3 = i0.ɵɵgetCurrentView();
55
- i0.ɵɵelementStart(0, "button", 18);
56
- i0.ɵɵlistener("click", function UserViewResource_Conditional_4_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onSaveAsList()); });
57
- i0.ɵɵconditionalCreate(1, UserViewResource_Conditional_4_Conditional_10_Conditional_1_Template, 1, 0, "i", 19)(2, UserViewResource_Conditional_4_Conditional_10_Conditional_2_Template, 1, 0, "i", 20);
52
+ i0.ɵɵelementStart(0, "button", 19);
53
+ i0.ɵɵlistener("click", function UserViewResource_Conditional_4_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OnCreateNewRecordInStandardForm()); });
54
+ i0.ɵɵelement(1, "i", 20);
55
+ i0.ɵɵelementStart(2, "span");
56
+ i0.ɵɵtext(3, "New in standard form");
57
+ i0.ɵɵelementEnd()();
58
+ } if (rf & 2) {
59
+ const ctx_r0 = i0.ɵɵnextContext(2);
60
+ i0.ɵɵproperty("title", i0.ɵɵinterpolate1("Create a new ", ctx_r0.entityInfo.Name, " record in the standard form (all form fields)"));
61
+ } }
62
+ function UserViewResource_Conditional_4_Conditional_11_Conditional_1_Template(rf, ctx) { if (rf & 1) {
63
+ i0.ɵɵelement(0, "i", 22);
64
+ } }
65
+ function UserViewResource_Conditional_4_Conditional_11_Conditional_2_Template(rf, ctx) { if (rf & 1) {
66
+ i0.ɵɵelement(0, "i", 23);
67
+ } }
68
+ function UserViewResource_Conditional_4_Conditional_11_Template(rf, ctx) { if (rf & 1) {
69
+ const _r4 = i0.ɵɵgetCurrentView();
70
+ i0.ɵɵelementStart(0, "button", 21);
71
+ i0.ɵɵlistener("click", function UserViewResource_Conditional_4_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onSaveAsList()); });
72
+ i0.ɵɵconditionalCreate(1, UserViewResource_Conditional_4_Conditional_11_Conditional_1_Template, 1, 0, "i", 22)(2, UserViewResource_Conditional_4_Conditional_11_Conditional_2_Template, 1, 0, "i", 23);
58
73
  i0.ɵɵelementStart(3, "span");
59
74
  i0.ɵɵtext(4);
60
75
  i0.ɵɵelementEnd()();
@@ -66,17 +81,17 @@ function UserViewResource_Conditional_4_Conditional_10_Template(rf, ctx) { if (r
66
81
  i0.ɵɵadvance(3);
67
82
  i0.ɵɵtextInterpolate(ctx_r0.isSavingAsList ? "Saving..." : "Save as List");
68
83
  } }
69
- function UserViewResource_Conditional_4_Conditional_11_Conditional_1_Template(rf, ctx) { if (rf & 1) {
70
- i0.ɵɵelement(0, "i", 19);
71
- } }
72
- function UserViewResource_Conditional_4_Conditional_11_Conditional_2_Template(rf, ctx) { if (rf & 1) {
84
+ function UserViewResource_Conditional_4_Conditional_12_Conditional_1_Template(rf, ctx) { if (rf & 1) {
73
85
  i0.ɵɵelement(0, "i", 22);
74
86
  } }
75
- function UserViewResource_Conditional_4_Conditional_11_Template(rf, ctx) { if (rf & 1) {
76
- const _r4 = i0.ɵɵgetCurrentView();
77
- i0.ɵɵelementStart(0, "button", 21);
78
- i0.ɵɵlistener("click", function UserViewResource_Conditional_4_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onExport()); });
79
- i0.ɵɵconditionalCreate(1, UserViewResource_Conditional_4_Conditional_11_Conditional_1_Template, 1, 0, "i", 19)(2, UserViewResource_Conditional_4_Conditional_11_Conditional_2_Template, 1, 0, "i", 22);
87
+ function UserViewResource_Conditional_4_Conditional_12_Conditional_2_Template(rf, ctx) { if (rf & 1) {
88
+ i0.ɵɵelement(0, "i", 25);
89
+ } }
90
+ function UserViewResource_Conditional_4_Conditional_12_Template(rf, ctx) { if (rf & 1) {
91
+ const _r5 = i0.ɵɵgetCurrentView();
92
+ i0.ɵɵelementStart(0, "button", 24);
93
+ i0.ɵɵlistener("click", function UserViewResource_Conditional_4_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onExport()); });
94
+ i0.ɵɵconditionalCreate(1, UserViewResource_Conditional_4_Conditional_12_Conditional_1_Template, 1, 0, "i", 22)(2, UserViewResource_Conditional_4_Conditional_12_Conditional_2_Template, 1, 0, "i", 25);
80
95
  i0.ɵɵelementStart(3, "span");
81
96
  i0.ɵɵtext(4);
82
97
  i0.ɵɵelementEnd()();
@@ -101,14 +116,15 @@ function UserViewResource_Conditional_4_Template(rf, ctx) { if (rf & 1) {
101
116
  i0.ɵɵelementStart(8, "span");
102
117
  i0.ɵɵtext(9, "New Record");
103
118
  i0.ɵɵelementEnd()();
104
- i0.ɵɵconditionalCreate(10, UserViewResource_Conditional_4_Conditional_10_Template, 5, 3, "button", 14);
119
+ i0.ɵɵconditionalCreate(10, UserViewResource_Conditional_4_Conditional_10_Template, 4, 2, "button", 14);
105
120
  i0.ɵɵconditionalCreate(11, UserViewResource_Conditional_4_Conditional_11_Template, 5, 3, "button", 15);
121
+ i0.ɵɵconditionalCreate(12, UserViewResource_Conditional_4_Conditional_12_Template, 5, 3, "button", 16);
106
122
  i0.ɵɵelementEnd()();
107
- i0.ɵɵelementStart(12, "mj-entity-viewer", 16, 1);
108
- i0.ɵɵlistener("RecordOpened", function UserViewResource_Conditional_4_Template_mj_entity_viewer_RecordOpened_12_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onRecordOpened($event)); })("OpenRelatedRecordRequested", function UserViewResource_Conditional_4_Template_mj_entity_viewer_OpenRelatedRecordRequested_12_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onOpenRelatedRecord($event)); })("AfterViewTypeChange", function UserViewResource_Conditional_4_Template_mj_entity_viewer_AfterViewTypeChange_12_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onViewTypeChanged()); })("DataLoaded", function UserViewResource_Conditional_4_Template_mj_entity_viewer_DataLoaded_12_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDataLoaded()); });
123
+ i0.ɵɵelementStart(13, "mj-entity-viewer", 17, 1);
124
+ i0.ɵɵlistener("RecordOpened", function UserViewResource_Conditional_4_Template_mj_entity_viewer_RecordOpened_13_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onRecordOpened($event)); })("OpenRelatedRecordRequested", function UserViewResource_Conditional_4_Template_mj_entity_viewer_OpenRelatedRecordRequested_13_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onOpenRelatedRecord($event)); })("AfterViewTypeChange", function UserViewResource_Conditional_4_Template_mj_entity_viewer_AfterViewTypeChange_13_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onViewTypeChanged()); })("DataLoaded", function UserViewResource_Conditional_4_Template_mj_entity_viewer_DataLoaded_13_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDataLoaded()); });
109
125
  i0.ɵɵelementEnd();
110
- i0.ɵɵelementStart(14, "mj-save-view-as-list-dialog", 17);
111
- i0.ɵɵlistener("Save", function UserViewResource_Conditional_4_Template_mj_save_view_as_list_dialog_Save_14_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onSaveAsListSubmit($event)); })("Cancel", function UserViewResource_Conditional_4_Template_mj_save_view_as_list_dialog_Cancel_14_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onSaveAsListCancelled()); });
126
+ i0.ɵɵelementStart(15, "mj-save-view-as-list-dialog", 18);
127
+ i0.ɵɵlistener("Save", function UserViewResource_Conditional_4_Template_mj_save_view_as_list_dialog_Save_15_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onSaveAsListSubmit($event)); })("Cancel", function UserViewResource_Conditional_4_Template_mj_save_view_as_list_dialog_Cancel_15_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onSaveAsListCancelled()); });
112
128
  i0.ɵɵelementEnd();
113
129
  } if (rf & 2) {
114
130
  const ctx_r0 = i0.ɵɵnextContext();
@@ -119,11 +135,13 @@ function UserViewResource_Conditional_4_Template(rf, ctx) { if (rf & 1) {
119
135
  i0.ɵɵadvance(2);
120
136
  i0.ɵɵproperty("title", i0.ɵɵinterpolate1("Create new ", ctx_r0.entityInfo.Name, " record"));
121
137
  i0.ɵɵadvance(4);
122
- i0.ɵɵconditional((ctx_r0.viewEntity == null ? null : ctx_r0.viewEntity.ID) ? 10 : -1);
138
+ i0.ɵɵconditional(ctx_r0.ShowNewInStandardForm ? 10 : -1);
139
+ i0.ɵɵadvance();
140
+ i0.ɵɵconditional((ctx_r0.viewEntity == null ? null : ctx_r0.viewEntity.ID) ? 11 : -1);
123
141
  i0.ɵɵadvance();
124
- i0.ɵɵconditional(ctx_r0.showFallbackExportButton ? 11 : -1);
142
+ i0.ɵɵconditional(ctx_r0.showFallbackExportButton ? 12 : -1);
125
143
  i0.ɵɵadvance();
126
- i0.ɵɵproperty("Entity", ctx_r0.entityInfo)("Provider", ctx_r0.Provider)("ViewEntity", ctx_r0.viewEntity)("GridState", ctx_r0.gridState)("AutoSaveView", true);
144
+ i0.ɵɵproperty("Entity", ctx_r0.entityInfo)("Provider", ctx_r0.Provider)("ViewEntity", ctx_r0.viewEntity)("AlternateBaseView", ctx_r0.AlternateBaseView)("GridState", ctx_r0.gridState)("AutoSaveView", true);
127
145
  i0.ɵɵadvance(2);
128
146
  i0.ɵɵproperty("Provider", ctx_r0.ProviderToUse)("Visible", ctx_r0.saveAsListDialogVisible)("ViewId", (ctx_r0.viewEntity == null ? null : ctx_r0.viewEntity.ID) ?? null)("ViewName", (ctx_r0.viewEntity == null ? null : ctx_r0.viewEntity.Name) ?? null)("RecordCount", ctx_r0.saveAsListRecordCount);
129
147
  } }
@@ -172,6 +190,11 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
172
190
  this.EntityInfo = value;
173
191
  }
174
192
  ViewEntity = null;
193
+ /**
194
+ * Show "New in standard form" (MJ#4755): a custom form hides the CodeGen
195
+ * form for this entity and the user may create. Resolved after load.
196
+ */
197
+ ShowNewInStandardForm = false;
175
198
  /** @deprecated Use {@link ViewEntity}. */
176
199
  get viewEntity() {
177
200
  return this.ViewEntity;
@@ -181,6 +204,7 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
181
204
  this.ViewEntity = value;
182
205
  }
183
206
  GridState = null;
207
+ AlternateBaseView = null;
184
208
  /** @deprecated Use {@link GridState}. */
185
209
  get gridState() {
186
210
  return this.GridState;
@@ -240,6 +264,7 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
240
264
  this.IsSavingAsList = value;
241
265
  }
242
266
  dataLoaded = false;
267
+ formResolver = inject(FormResolverService);
243
268
  get metadata() { return this.ProviderToUse; }
244
269
  constructor(cdr, exportService) {
245
270
  super();
@@ -268,19 +293,23 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
268
293
  set Data(value) {
269
294
  const previousRecordId = super.Data?.ResourceRecordID;
270
295
  const previousEntity = super.Data?.Configuration?.Entity;
296
+ const previousAbv = super.Data?.Configuration?.AlternateBaseView;
271
297
  super.Data = value;
272
298
  const newRecordId = value?.ResourceRecordID;
273
299
  const newEntity = value?.Configuration?.Entity;
300
+ const newAbv = value?.Configuration?.AlternateBaseView;
274
301
  // View-type (grid/cards/timeline/map) and per-view-type config are now resolved
275
302
  // internally by mj-entity-viewer from the saved view's ViewTypeID — nothing to read here.
276
- // Load on first set, or when the view/entity has changed
277
- if (!this.dataLoaded || newRecordId !== previousRecordId || newEntity !== previousEntity) {
303
+ // Load on first set, or when the view/entity/alternateBaseView has changed
304
+ if (!this.dataLoaded || newRecordId !== previousRecordId || newEntity !== previousEntity || newAbv !== previousAbv) {
278
305
  this.dataLoaded = true;
279
306
  // Reset state before loading new view
280
307
  this.EntityInfo = null;
281
308
  this.ViewEntity = null;
282
309
  this.GridState = null;
310
+ this.AlternateBaseView = null;
283
311
  this.errorMessage = null;
312
+ this.ShowNewInStandardForm = false;
284
313
  this.loadView();
285
314
  }
286
315
  }
@@ -311,11 +340,13 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
311
340
  }
312
341
  // Case 2: Load dynamic view by entity name
313
342
  else if (data.Configuration?.Entity) {
314
- await this.loadDynamicView(data.Configuration.Entity, data.Configuration.ExtraFilter);
343
+ await this.loadDynamicView(data.Configuration.Entity, data.Configuration.ExtraFilter, data.Configuration.AlternateBaseView);
315
344
  }
316
345
  else {
317
346
  this.errorMessage = 'No view ID or entity specified';
318
347
  }
348
+ // Deliberately not awaited: the extra button must never hold up the view.
349
+ void this.refreshStandardFormCreate();
319
350
  }
320
351
  catch (error) {
321
352
  console.error('Error loading view:', error);
@@ -366,9 +397,9 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
366
397
  // [AutoSaveView]="true", saves changes back) — nothing to wire here.
367
398
  }
368
399
  /**
369
- * Load a dynamic view (no saved view, just entity + filter)
400
+ * Load a dynamic view (no saved view, just entity + filter + optional alternate base view)
370
401
  */
371
- async loadDynamicView(entityName, _extraFilter) {
402
+ async loadDynamicView(entityName, _extraFilter, alternateBaseView) {
372
403
  const entity = this.metadata.Entities.find(e => e.Name.trim().toLowerCase() === entityName.trim().toLowerCase());
373
404
  if (!entity) {
374
405
  throw new Error(`Entity '${entityName}' not found`);
@@ -376,6 +407,7 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
376
407
  this.EntityInfo = entity;
377
408
  this.ViewEntity = null;
378
409
  this.GridState = null;
410
+ this.AlternateBaseView = alternateBaseView || null;
379
411
  // For dynamic views, we could create a synthetic viewEntity with just the WhereClause
380
412
  // but for now, we'll rely on the entity-viewer's default behavior
381
413
  }
@@ -556,6 +588,40 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
556
588
  onCreateNewRecord() {
557
589
  return this.OnCreateNewRecord();
558
590
  }
591
+ /**
592
+ * Create a new record in the CodeGen standard form (MJ#4755) — the escape
593
+ * hatch for entities whose custom form cannot create records.
594
+ */
595
+ OnCreateNewRecordInStandardForm() {
596
+ if (!this.EntityInfo)
597
+ return;
598
+ this.navigationService.OpenNewEntityRecord(this.EntityInfo.Name, { formMode: 'standard' });
599
+ }
600
+ /**
601
+ * Decide whether to offer "New in standard form" for the loaded entity.
602
+ * Discards the answer if the view moved to another entity meanwhile.
603
+ */
604
+ async refreshStandardFormCreate() {
605
+ const entity = this.EntityInfo;
606
+ if (!entity)
607
+ return;
608
+ let show = false;
609
+ try {
610
+ const p = this.ProviderToUse;
611
+ const res = await this.formResolver.ResolveFormForEntity(entity, p.CurrentUser, p);
612
+ const canCreate = entity.GetUserPermisions(p.CurrentUser).CanCreate;
613
+ show = ShouldOfferStandardFormCreate(res, canCreate);
614
+ }
615
+ catch (err) {
616
+ LogError(`ViewResource: could not resolve forms for "${entity.Name}": ${err instanceof Error ? err.message : String(err)}`);
617
+ }
618
+ if (this.EntityInfo !== entity)
619
+ return;
620
+ this.ShowNewInStandardForm = show;
621
+ // Safe variant: this runs after an await in a fire-and-forget promise,
622
+ // so the view may be destroyed (tab closed) or mid-pass by now.
623
+ SafeDetectChanges(this.cdr);
624
+ }
559
625
  /**
560
626
  * Open the Save-as-List dialog. Only meaningful for saved views (a
561
627
  * ViewID is required to materialize). Dynamic views fall back to a
@@ -646,14 +712,14 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
646
712
  let _t;
647
713
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.ContainerElement = _t.first);
648
714
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.EntityViewerRef = _t.first);
649
- } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 1, consts: [["container", ""], ["entityViewer", ""], [1, "view-resource-container"], [1, "view-loading-state"], [1, "view-error-state"], ["text", "Loading view...", "size", "large"], [1, "fas", "fa-exclamation-triangle"], [1, "view-header"], [1, "header-left"], [1, "view-title"], [1, "view-description"], [1, "header-right"], [1, "action-button", "create-button", 3, "click", "title"], [1, "fa-solid", "fa-plus"], ["title", "Materialize these results as a static List", 1, "action-button", "save-as-list-button", 3, "disabled"], ["title", "Export", 1, "action-button", "export-button", 3, "disabled"], [3, "RecordOpened", "OpenRelatedRecordRequested", "AfterViewTypeChange", "DataLoaded", "Entity", "Provider", "ViewEntity", "GridState", "AutoSaveView"], [3, "Save", "Cancel", "Provider", "Visible", "ViewId", "ViewName", "RecordCount"], ["title", "Materialize these results as a static List", 1, "action-button", "save-as-list-button", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-floppy-disk"], ["title", "Export", 1, "action-button", "export-button", 3, "click", "disabled"], [1, "fa-solid", "fa-file-excel"]], template: function UserViewResource_Template(rf, ctx) { if (rf & 1) {
715
+ } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 1, consts: [["container", ""], ["entityViewer", ""], [1, "view-resource-container"], [1, "view-loading-state"], [1, "view-error-state"], ["text", "Loading view...", "size", "large"], [1, "fas", "fa-exclamation-triangle"], [1, "view-header"], [1, "header-left"], [1, "view-title"], [1, "view-description"], [1, "header-right"], [1, "action-button", "create-button", 3, "click", "title"], [1, "fa-solid", "fa-plus"], ["mjButton", "", "Variant", "outline", "type", "button", 1, "action-button", 3, "title"], ["title", "Materialize these results as a static List", 1, "action-button", "save-as-list-button", 3, "disabled"], ["title", "Export", 1, "action-button", "export-button", 3, "disabled"], [3, "RecordOpened", "OpenRelatedRecordRequested", "AfterViewTypeChange", "DataLoaded", "Entity", "Provider", "ViewEntity", "AlternateBaseView", "GridState", "AutoSaveView"], [3, "Save", "Cancel", "Provider", "Visible", "ViewId", "ViewName", "RecordCount"], ["mjButton", "", "Variant", "outline", "type", "button", 1, "action-button", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid", "fa-table-list"], ["title", "Materialize these results as a static List", 1, "action-button", "save-as-list-button", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-floppy-disk"], ["title", "Export", 1, "action-button", "export-button", 3, "click", "disabled"], [1, "fa-solid", "fa-file-excel"]], template: function UserViewResource_Template(rf, ctx) { if (rf & 1) {
650
716
  i0.ɵɵelementStart(0, "div", 2, 0);
651
- i0.ɵɵconditionalCreate(2, UserViewResource_Conditional_2_Template, 2, 0, "div", 3)(3, UserViewResource_Conditional_3_Template, 4, 1, "div", 4)(4, UserViewResource_Conditional_4_Template, 15, 16);
717
+ i0.ɵɵconditionalCreate(2, UserViewResource_Conditional_2_Template, 2, 0, "div", 3)(3, UserViewResource_Conditional_3_Template, 4, 1, "div", 4)(4, UserViewResource_Conditional_4_Template, 16, 18);
652
718
  i0.ɵɵelementEnd();
653
719
  } if (rf & 2) {
654
720
  i0.ɵɵadvance(2);
655
721
  i0.ɵɵconditional(ctx.isLoading ? 2 : ctx.errorMessage ? 3 : ctx.entityInfo ? 4 : -1);
656
- } }, dependencies: [i2.LoadingComponent, i3.EntityViewerComponent, i4.SaveViewAsListDialogComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .view-resource-container[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .view-header[_ngcontent-%COMP%] {\n padding: 16px 20px 8px 20px;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n }\n .header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n .header-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n }\n .view-title[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--text-primary, #1a1a1a);\n }\n .view-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--text-secondary, #666);\n }\n .action-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n .action-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n }\n .action-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .action-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n .create-button[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n }\n .create-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n }\n .export-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n .view-loading-state[_ngcontent-%COMP%], \n .view-error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n }\n .view-error-state[_ngcontent-%COMP%] {\n color: var(--danger-color, #dc3545);\n }\n .view-error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2rem;\n }\n .view-error-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n }\n mj-entity-viewer[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n }"] });
722
+ } }, dependencies: [i2.LoadingComponent, i3.EntityViewerComponent, i4.SaveViewAsListDialogComponent, i5.MJButtonDirective], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .view-resource-container[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .view-header[_ngcontent-%COMP%] {\n padding: 16px 20px 8px 20px;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n }\n .header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n .header-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n }\n .view-title[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--text-primary, #1a1a1a);\n }\n .view-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--text-secondary, #666);\n }\n .action-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n .action-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n }\n .action-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .action-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n .create-button[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n }\n .create-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n }\n .export-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n .view-loading-state[_ngcontent-%COMP%], \n .view-error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n }\n .view-error-state[_ngcontent-%COMP%] {\n color: var(--danger-color, #dc3545);\n }\n .view-error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2rem;\n }\n .view-error-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n }\n mj-entity-viewer[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n }"] });
657
723
  };
658
724
  UserViewResource = __decorate([
659
725
  RegisterClass(BaseResourceComponent, 'ViewResource')
@@ -661,7 +727,7 @@ UserViewResource = __decorate([
661
727
  export { UserViewResource };
662
728
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserViewResource, [{
663
729
  type: Component,
664
- args: [{ standalone: false, selector: 'mj-userview-resource', template: "<div #container class=\"view-resource-container\">\n @if (isLoading) {\n <div class=\"view-loading-state\">\n <mj-loading text=\"Loading view...\" size=\"large\"></mj-loading>\n </div>\n } @else if (errorMessage) {\n <div class=\"view-error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ errorMessage }}</p>\n </div>\n } @else if (entityInfo) {\n <!-- Header with title and action buttons -->\n <div class=\"view-header\">\n <div class=\"header-left\">\n <h2 class=\"view-title\">{{ viewEntity?.Name || entityInfo.Name }}</h2>\n @if (viewEntity?.Description) {\n <p class=\"view-description\">{{ viewEntity!.Description }}</p>\n }\n </div>\n <div class=\"header-right\">\n <!-- Create New Record Button -->\n <button\n class=\"action-button create-button\"\n (click)=\"onCreateNewRecord()\"\n title=\"Create new {{ entityInfo.Name }} record\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New Record</span>\n </button>\n\n <!-- Save as List Button \u2014 only meaningful for saved (non-dynamic) views. -->\n @if (viewEntity?.ID) {\n <button\n class=\"action-button save-as-list-button\"\n (click)=\"onSaveAsList()\"\n [disabled]=\"isSavingAsList\"\n title=\"Materialize these results as a static List\">\n @if (isSavingAsList) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i>\n }\n <span>{{ isSavingAsList ? 'Saving...' : 'Save as List' }}</span>\n </button>\n }\n <!-- Fallback Export button. Shown ONLY for view types that lack their own export UI\n (Cards / Map / Timeline). The Grid renderer has its own in-toolbar Export (full\n result set + format/sampling dialog), so this is suppressed there to avoid a\n duplicate/confusing second button. -->\n @if (showFallbackExportButton) {\n <button\n class=\"action-button export-button\"\n (click)=\"onExport()\"\n [disabled]=\"isExporting\"\n title=\"Export\">\n @if (isExporting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-file-excel\"></i>\n }\n <span>{{ isExporting ? 'Exporting...' : 'Export' }}</span>\n </button>\n }\n </div>\n </div>\n\n <!-- Entity Viewer -->\n <mj-entity-viewer\n #entityViewer\n [Entity]=\"entityInfo\"\n [Provider]=\"Provider\"\n [ViewEntity]=\"viewEntity\"\n [GridState]=\"gridState\"\n [AutoSaveView]=\"true\"\n (RecordOpened)=\"onRecordOpened($any($event))\"\n (OpenRelatedRecordRequested)=\"onOpenRelatedRecord($event)\"\n (AfterViewTypeChange)=\"onViewTypeChanged()\"\n (DataLoaded)=\"onDataLoaded()\">\n </mj-entity-viewer>\n\n <!-- Save-as-List dialog -->\n <mj-save-view-as-list-dialog\n [Provider]=\"ProviderToUse\"\n [Visible]=\"saveAsListDialogVisible\"\n [ViewId]=\"viewEntity?.ID ?? null\"\n [ViewName]=\"viewEntity?.Name ?? null\"\n [RecordCount]=\"saveAsListRecordCount\"\n (Save)=\"onSaveAsListSubmit($event)\"\n (Cancel)=\"onSaveAsListCancelled()\">\n </mj-save-view-as-list-dialog>\n }\n</div>\n", styles: ["\n :host {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .view-resource-container {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .view-header {\n padding: 16px 20px 8px 20px;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n }\n .header-left {\n flex: 1;\n min-width: 0;\n }\n .header-right {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n }\n .view-title {\n margin: 0 0 4px 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--text-primary, #1a1a1a);\n }\n .view-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--text-secondary, #666);\n }\n .action-button {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n .action-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n }\n .action-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .action-button i {\n font-size: 0.875rem;\n }\n .create-button {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n }\n .create-button:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n }\n .export-button:hover:not(:disabled) {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n .view-loading-state,\n .view-error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n }\n .view-error-state {\n color: var(--danger-color, #dc3545);\n }\n .view-error-state i {\n font-size: 2rem;\n }\n .view-error-state p {\n margin: 0;\n font-size: 1rem;\n }\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n "] }]
730
+ args: [{ standalone: false, selector: 'mj-userview-resource', template: "<div #container class=\"view-resource-container\">\n @if (isLoading) {\n <div class=\"view-loading-state\">\n <mj-loading text=\"Loading view...\" size=\"large\"></mj-loading>\n </div>\n } @else if (errorMessage) {\n <div class=\"view-error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ errorMessage }}</p>\n </div>\n } @else if (entityInfo) {\n <!-- Header with title and action buttons -->\n <div class=\"view-header\">\n <div class=\"header-left\">\n <h2 class=\"view-title\">{{ viewEntity?.Name || entityInfo.Name }}</h2>\n @if (viewEntity?.Description) {\n <p class=\"view-description\">{{ viewEntity!.Description }}</p>\n }\n </div>\n <div class=\"header-right\">\n <!-- Create New Record Button -->\n <button\n class=\"action-button create-button\"\n (click)=\"onCreateNewRecord()\"\n title=\"Create new {{ entityInfo.Name }} record\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New Record</span>\n </button>\n\n <!-- A custom form hides the CodeGen form for this entity (MJ#4755). -->\n @if (ShowNewInStandardForm) {\n <button mjButton Variant=\"outline\" type=\"button\" class=\"action-button\"\n (click)=\"OnCreateNewRecordInStandardForm()\"\n title=\"Create a new {{ entityInfo.Name }} record in the standard form (all form fields)\">\n <i class=\"fa-solid fa-table-list\" aria-hidden=\"true\"></i>\n <span>New in standard form</span>\n </button>\n }\n\n <!-- Save as List Button \u2014 only meaningful for saved (non-dynamic) views. -->\n @if (viewEntity?.ID) {\n <button\n class=\"action-button save-as-list-button\"\n (click)=\"onSaveAsList()\"\n [disabled]=\"isSavingAsList\"\n title=\"Materialize these results as a static List\">\n @if (isSavingAsList) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i>\n }\n <span>{{ isSavingAsList ? 'Saving...' : 'Save as List' }}</span>\n </button>\n }\n <!-- Fallback Export button. Shown ONLY for view types that lack their own export UI\n (Cards / Map / Timeline). The Grid renderer has its own in-toolbar Export (full\n result set + format/sampling dialog), so this is suppressed there to avoid a\n duplicate/confusing second button. -->\n @if (showFallbackExportButton) {\n <button\n class=\"action-button export-button\"\n (click)=\"onExport()\"\n [disabled]=\"isExporting\"\n title=\"Export\">\n @if (isExporting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-file-excel\"></i>\n }\n <span>{{ isExporting ? 'Exporting...' : 'Export' }}</span>\n </button>\n }\n </div>\n </div>\n\n <!-- Entity Viewer -->\n <mj-entity-viewer\n #entityViewer\n [Entity]=\"entityInfo\"\n [Provider]=\"Provider\"\n [ViewEntity]=\"viewEntity\"\n [AlternateBaseView]=\"AlternateBaseView\"\n [GridState]=\"gridState\"\n [AutoSaveView]=\"true\"\n (RecordOpened)=\"onRecordOpened($any($event))\"\n (OpenRelatedRecordRequested)=\"onOpenRelatedRecord($event)\"\n (AfterViewTypeChange)=\"onViewTypeChanged()\"\n (DataLoaded)=\"onDataLoaded()\">\n </mj-entity-viewer>\n\n <!-- Save-as-List dialog -->\n <mj-save-view-as-list-dialog\n [Provider]=\"ProviderToUse\"\n [Visible]=\"saveAsListDialogVisible\"\n [ViewId]=\"viewEntity?.ID ?? null\"\n [ViewName]=\"viewEntity?.Name ?? null\"\n [RecordCount]=\"saveAsListRecordCount\"\n (Save)=\"onSaveAsListSubmit($event)\"\n (Cancel)=\"onSaveAsListCancelled()\">\n </mj-save-view-as-list-dialog>\n }\n</div>\n", styles: ["\n :host {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .view-resource-container {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .view-header {\n padding: 16px 20px 8px 20px;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n }\n .header-left {\n flex: 1;\n min-width: 0;\n }\n .header-right {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n }\n .view-title {\n margin: 0 0 4px 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--text-primary, #1a1a1a);\n }\n .view-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--text-secondary, #666);\n }\n .action-button {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n .action-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n }\n .action-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .action-button i {\n font-size: 0.875rem;\n }\n .create-button {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n }\n .create-button:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n }\n .export-button:hover:not(:disabled) {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n .view-loading-state,\n .view-error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n }\n .view-error-state {\n color: var(--danger-color, #dc3545);\n }\n .view-error-state i {\n font-size: 2rem;\n }\n .view-error-state p {\n margin: 0;\n font-size: 1rem;\n }\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n "] }]
665
731
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.ExportService }], { ContainerElement: [{
666
732
  type: ViewChild,
667
733
  args: ['container', { static: true }]
@@ -669,5 +735,5 @@ export { UserViewResource };
669
735
  type: ViewChild,
670
736
  args: ['entityViewer']
671
737
  }] }); })();
672
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserViewResource, { className: "UserViewResource", filePath: "src/lib/resource-wrappers/view-resource.component.ts", lineNumber: 139 }); })();
738
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserViewResource, { className: "UserViewResource", filePath: "src/lib/resource-wrappers/view-resource.component.ts", lineNumber: 141 }); })();
673
739
  //# sourceMappingURL=view-resource.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"view-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/view-resource.component.ts","../../../src/lib/resource-wrappers/view-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ViewChild, ElementRef, ChangeDetectorRef, OnInit } from '@angular/core';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { ResourceData, MJUserViewEntityExtended, ViewInfo } from '@memberjunction/core-entities';\nimport { RegisterClass, MJGlobal, MJEventType , UUIDsEqual } from '@memberjunction/global';\nimport { CompositeKey, Metadata, EntityInfo, BaseEntity, BaseEntityEvent } from '@memberjunction/core';\nimport { RecordOpenedEvent, ViewGridState, EntityViewerComponent, ViewRelatedRecordNavigation, ExportColumnTypeForSQLType } from '@memberjunction/ng-entity-viewer';\nimport { ExportService } from '@memberjunction/ng-export-service';\nimport { ExportColumn } from '@memberjunction/export-engine';\nimport { GraphQLDataProvider, GraphQLListsClient } from '@memberjunction/graphql-dataprovider';\nimport type { SaveViewAsListResult } from '@memberjunction/ng-list-management';\nimport { debounceTime, filter, takeUntil } from 'rxjs/operators';\n/**\n * UserViewResource - Resource wrapper for displaying User Views in tabs\n *\n * This component wraps the EntityViewerComponent to display view data.\n * It loads the view configuration and entity, then renders the data grid/cards.\n *\n * Key features:\n * - Loads view by ID from ResourceRecordID\n * - Supports dynamic views by entity name + extra filter\n * - Applies view's WhereClause, GridState, and SortState\n * - Opens records in new tabs via NavigationService\n */\n@RegisterClass(BaseResourceComponent, 'ViewResource')\n@Component({\n standalone: false,\n selector: 'mj-userview-resource',\n templateUrl: './view-resource.component.html',\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .view-resource-container {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .view-header {\n padding: 16px 20px 8px 20px;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n }\n .header-left {\n flex: 1;\n min-width: 0;\n }\n .header-right {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n }\n .view-title {\n margin: 0 0 4px 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--text-primary, #1a1a1a);\n }\n .view-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--text-secondary, #666);\n }\n .action-button {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n .action-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n }\n .action-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .action-button i {\n font-size: 0.875rem;\n }\n .create-button {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n }\n .create-button:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n }\n .export-button:hover:not(:disabled) {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n .view-loading-state,\n .view-error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n }\n .view-error-state {\n color: var(--danger-color, #dc3545);\n }\n .view-error-state i {\n font-size: 2rem;\n }\n .view-error-state p {\n margin: 0;\n font-size: 1rem;\n }\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n `]\n})\nexport class UserViewResource extends BaseResourceComponent {\n @ViewChild('container', { static: true }) ContainerElement!: ElementRef<HTMLDivElement>;\n\n /** @deprecated Use {@link ContainerElement}. */\n get containerElement(): ElementRef<HTMLDivElement> {\n return this.ContainerElement;\n }\n /** @deprecated Use {@link ContainerElement}. */\n set containerElement(value: ElementRef<HTMLDivElement>) {\n this.ContainerElement = value;\n }\n @ViewChild('entityViewer') EntityViewerRef?: EntityViewerComponent;\n\n /** @deprecated Use {@link EntityViewerRef}. */\n get entityViewerRef(): EntityViewerComponent | undefined {\n return this.EntityViewerRef;\n }\n /** @deprecated Use {@link EntityViewerRef}. */\n set entityViewerRef(value: EntityViewerComponent | undefined) {\n this.EntityViewerRef = value;\n }\n\n public isLoading: boolean = false;\n public errorMessage: string | null = null;\n public EntityInfo: EntityInfo | null = null;\n\n /** @deprecated Use {@link EntityInfo}. */\n public get entityInfo(): EntityInfo | null {\n return this.EntityInfo;\n }\n /** @deprecated Use {@link EntityInfo}. */\n public set entityInfo(value: EntityInfo | null) {\n this.EntityInfo = value;\n }\n public ViewEntity: MJUserViewEntityExtended | null = null;\n\n /** @deprecated Use {@link ViewEntity}. */\n public get viewEntity(): MJUserViewEntityExtended | null {\n return this.ViewEntity;\n }\n /** @deprecated Use {@link ViewEntity}. */\n public set viewEntity(value: MJUserViewEntityExtended | null) {\n this.ViewEntity = value;\n }\n public GridState: ViewGridState | null = null;\n\n /** @deprecated Use {@link GridState}. */\n public get gridState(): ViewGridState | null {\n return this.GridState;\n }\n /** @deprecated Use {@link GridState}. */\n public set gridState(value: ViewGridState | null) {\n this.GridState = value;\n }\n\n // Export state. The header Export button is a FALLBACK shown only for view types that don't\n // provide their own export UI (Cards / Map / Timeline). The Grid renderer has its own in-toolbar\n // Export (full result set + format/sampling dialog), so we suppress this one there to avoid a\n // duplicate/confusing second button — while keeping export available for every other view type.\n public IsExporting: boolean = false;\n\n /** @deprecated Use {@link IsExporting}. */\n public get isExporting(): boolean {\n return this.IsExporting;\n }\n /** @deprecated Use {@link IsExporting}. */\n public set isExporting(value: boolean) {\n this.IsExporting = value;\n }\n public ShowFallbackExportButton: boolean = false;\n\n /** @deprecated Use {@link ShowFallbackExportButton}. */\n public get showFallbackExportButton(): boolean {\n return this.ShowFallbackExportButton;\n }\n /** @deprecated Use {@link ShowFallbackExportButton}. */\n public set showFallbackExportButton(value: boolean) {\n this.ShowFallbackExportButton = value;\n }\n\n // Save-as-list dialog state\n public SaveAsListDialogVisible = false;\n\n /** @deprecated Use {@link SaveAsListDialogVisible}. */\n public get saveAsListDialogVisible() {\n return this.SaveAsListDialogVisible;\n }\n /** @deprecated Use {@link SaveAsListDialogVisible}. */\n public set saveAsListDialogVisible(value) {\n this.SaveAsListDialogVisible = value;\n }\n public SaveAsListRecordCount: number | null = null;\n\n /** @deprecated Use {@link SaveAsListRecordCount}. */\n public get saveAsListRecordCount(): number | null {\n return this.SaveAsListRecordCount;\n }\n /** @deprecated Use {@link SaveAsListRecordCount}. */\n public set saveAsListRecordCount(value: number | null) {\n this.SaveAsListRecordCount = value;\n }\n public IsSavingAsList = false;\n\n /** @deprecated Use {@link IsSavingAsList}. */\n public get isSavingAsList() {\n return this.IsSavingAsList;\n }\n /** @deprecated Use {@link IsSavingAsList}. */\n public set isSavingAsList(value) {\n this.IsSavingAsList = value;\n }\n\n private dataLoaded = false;\n private get metadata() { return this.ProviderToUse; }\n constructor(\n private cdr: ChangeDetectorRef,\n private exportService: ExportService\n ) {\n super();\n }\n\n public override ngOnInit(): void {\n super.ngOnInit();\n\n // Refresh when rows of this view's entity change: a local save/delete, or a server-side\n // write announced as remote-invalidate (a clone, or another server). Debounced, so a burst\n // of writes (a clone creating many rows) reloads the view once.\n MJGlobal.Instance.GetEventListener()\n .pipe(\n filter((event) => {\n if (event.event !== MJEventType.ComponentEvent || event.eventCode !== BaseEntity.BaseEventCode) return false;\n const entityEvent = event.args as BaseEntityEvent;\n const type = entityEvent?.type;\n if (type !== 'save' && type !== 'delete' && type !== 'remote-invalidate') return false;\n const affectedName = (entityEvent.baseEntity?.EntityInfo?.Name ?? entityEvent.entityName)?.trim().toLowerCase();\n return !!affectedName && affectedName === this.entityInfo?.Name?.trim().toLowerCase();\n }),\n debounceTime(300),\n takeUntil(this.destroy$)\n )\n // In place: a change made elsewhere shouldn't move the user off their page or sort.\n .subscribe(() => this.entityViewerRef?.RefreshInPlace());\n }\n\n override set Data(value: ResourceData) {\n const previousRecordId = super.Data?.ResourceRecordID;\n const previousEntity = super.Data?.Configuration?.Entity;\n super.Data = value;\n\n const newRecordId = value?.ResourceRecordID;\n const newEntity = value?.Configuration?.Entity;\n\n // View-type (grid/cards/timeline/map) and per-view-type config are now resolved\n // internally by mj-entity-viewer from the saved view's ViewTypeID — nothing to read here.\n\n // Load on first set, or when the view/entity has changed\n if (!this.dataLoaded || newRecordId !== previousRecordId || newEntity !== previousEntity) {\n this.dataLoaded = true;\n // Reset state before loading new view\n this.EntityInfo = null;\n this.ViewEntity = null;\n this.GridState = null;\n this.errorMessage = null;\n this.loadView();\n }\n }\n\n override get Data(): ResourceData {\n return super.Data;\n }\n\n /**\n * Load the view and entity based on ResourceData\n */\n private async loadView(): Promise<void> {\n const data = this.Data;\n\n if (!data) {\n this.NotifyLoadComplete();\n return;\n }\n\n this.isLoading = true;\n this.errorMessage = null;\n this.NotifyLoadStarted();\n this.cdr.detectChanges();\n\n try {\n // NavigationService.OpenDynamicView stamps the special marker 'dynamic' as the\n // record ID (tabs require ResourceRecordId) — that is NOT a saved-view ID.\n const recordId = data.ResourceRecordID;\n const isDynamicMarker = typeof recordId === 'string' && recordId.trim().toLowerCase() === 'dynamic';\n // Case 1: Load view by ID\n if (recordId && !isDynamicMarker) {\n await this.loadViewById(recordId);\n }\n // Case 2: Load dynamic view by entity name\n else if (data.Configuration?.Entity) {\n await this.loadDynamicView(\n data.Configuration.Entity as string,\n data.Configuration.ExtraFilter as string | undefined\n );\n }\n else {\n this.errorMessage = 'No view ID or entity specified';\n }\n } catch (error) {\n console.error('Error loading view:', error);\n this.errorMessage = error instanceof Error ? error.message : 'Failed to load view';\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n\n // If there was an error, notify load complete now\n if (this.errorMessage) {\n this.NotifyLoadComplete();\n }\n // Otherwise, wait for dataLoaded event from entity-viewer\n }\n }\n\n /**\n * Load a saved view by its ID\n */\n private async loadViewById(viewId: string): Promise<void> {\n // Load the view entity\n const view = await ViewInfo.GetViewEntity(viewId);\n\n if (!view) {\n throw new Error(`View with ID ${viewId} not found`);\n }\n\n this.ViewEntity = view as MJUserViewEntityExtended;\n\n // Check permissions\n if (!this.ViewEntity.UserCanView) {\n throw new Error('You do not have permission to view this view');\n }\n\n // Load the entity info\n const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, this.ViewEntity!.EntityID));\n\n if (!entity) {\n throw new Error(`Entity for view not found`);\n }\n\n this.EntityInfo = entity;\n\n // Parse grid state if available\n if (this.ViewEntity.GridState) {\n try {\n this.GridState = JSON.parse(this.ViewEntity.GridState) as ViewGridState;\n } catch (e) {\n console.warn('Failed to parse GridState:', e);\n this.GridState = null;\n }\n }\n\n // View-type + per-view-type config persistence is fully owned by mj-entity-viewer\n // (it reads ViewTypeID + DisplayState.viewTypeConfigs off the [viewEntity] and, with\n // [AutoSaveView]=\"true\", saves changes back) — nothing to wire here.\n }\n\n /**\n * Load a dynamic view (no saved view, just entity + filter)\n */\n private async loadDynamicView(entityName: string, _extraFilter?: string): Promise<void> {\n const entity = this.metadata.Entities.find(\n e => e.Name.trim().toLowerCase() === entityName.trim().toLowerCase()\n );\n\n if (!entity) {\n throw new Error(`Entity '${entityName}' not found`);\n }\n\n this.EntityInfo = entity;\n this.ViewEntity = null;\n this.GridState = null;\n\n // For dynamic views, we could create a synthetic viewEntity with just the WhereClause\n // but for now, we'll rely on the entity-viewer's default behavior\n }\n\n /**\n * Handle record opened event - open in new tab\n */\n public OnRecordOpened(event: RecordOpenedEvent): void {\n if (event && event.entity && event.compositeKey) {\n this.navigationService.OpenEntityRecord(event.entity.Name, event.compositeKey);\n }\n }\n\n /** @deprecated Use {@link OnRecordOpened}. */\n public onRecordOpened(event: RecordOpenedEvent): void {\n return this.OnRecordOpened(event);\n }\n\n /**\n * Handle a related-record navigation requested from within a view-type renderer\n * (e.g. a foreign-key cell) - open the target record in a new tab.\n */\n public OnOpenRelatedRecord(nav: ViewRelatedRecordNavigation): void {\n if (nav?.entityName && nav.recordKey != null) {\n // The related entity is arbitrary, so its key column can have any name — resolve the key\n // against its metadata rather than hardcoding `ID` via FromID.\n const entityInfo = this.metadata.EntityByName(nav.entityName);\n this.navigationService.OpenEntityRecord(nav.entityName, CompositeKey.FromURLSegment(entityInfo, String(nav.recordKey)));\n }\n }\n\n /** @deprecated Use {@link OnOpenRelatedRecord}. */\n public onOpenRelatedRecord(nav: ViewRelatedRecordNavigation): void {\n return this.OnOpenRelatedRecord(nav);\n }\n\n /**\n * Handle data loaded event from entity-viewer\n */\n public OnDataLoaded(): void {\n this.NotifyLoadComplete();\n this.refreshFallbackExportVisibility();\n }\n\n /** @deprecated Use {@link OnDataLoaded}. */\n public onDataLoaded(): void {\n return this.OnDataLoaded();\n }\n\n /** The active view type changed — recompute whether the fallback Export button is needed. */\n public OnViewTypeChanged(): void {\n this.refreshFallbackExportVisibility();\n }\n\n /** @deprecated Use {@link OnViewTypeChanged}. */\n public onViewTypeChanged(): void {\n return this.OnViewTypeChanged();\n }\n\n /**\n * Show the wrapper's Export button only for view types that don't ship their own export UI. The\n * entity-viewer reports this via {@link EntityViewerComponent.ActiveViewTypeHasOwnExport} (true for\n * the Grid renderer, false for Cards / Map / Timeline). Uses a cached flag + explicit change\n * detection to avoid an ExpressionChanged error from reading child state during a CD pass.\n */\n private refreshFallbackExportVisibility(): void {\n const next = !!this.EntityViewerRef && !this.EntityViewerRef.ActiveViewTypeHasOwnExport;\n if (next !== this.ShowFallbackExportButton) {\n this.ShowFallbackExportButton = next;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Fallback export for view types without their own export UI (Cards / Map / Timeline). Pulls the\n * FULL result set via the entity-viewer's capped, filter/sort-aware fetch (same path the grid uses,\n * so it's bounded and warns past the cap) and writes an Excel file.\n */\n public async OnExport(): Promise<void> {\n // Never fail silently — a \"nothing happens\" click is impossible to diagnose. Surface the\n // reason both in the UI and the console.\n if (!this.EntityInfo || !this.EntityViewerRef) {\n console.error('[ViewResource] Export: viewer not ready', {\n hasEntity: !!this.EntityInfo, hasViewer: !!this.EntityViewerRef\n });\n this.showNotification('Export is not ready yet — try again in a moment.', 'error', 5000);\n return;\n }\n this.IsExporting = true;\n this.cdr.detectChanges();\n this.showNotification('Preparing your Excel export…', 'info', 2000);\n try {\n const rows = await this.EntityViewerRef.FetchAllRowsForExport();\n if (!rows || rows.length === 0) {\n this.showNotification('Nothing to export — the view returned no records.', 'warning', 5000);\n return;\n }\n const result = await this.exportService.toExcel(rows, {\n fileName: this.buildExportFileName(),\n columns: this.buildExportColumns(),\n includeHeaders: true\n });\n if (result.success) {\n this.exportService.downloadResult(result);\n this.showNotification(`Exported ${rows.length.toLocaleString()} record(s) to Excel.`, 'success', 3000);\n } else {\n this.showNotification('Export failed while building the file.', 'error', 5000);\n console.error('[ViewResource] Export: toExcel returned failure', result);\n }\n } catch (e) {\n this.showNotification('Error exporting data — see console for details.', 'error', 5000);\n console.error('[ViewResource] Export error:', e);\n } finally {\n this.IsExporting = false;\n this.cdr.detectChanges();\n }\n }\n\n /** @deprecated Use {@link OnExport}. */\n public async onExport(): Promise<void> {\n return this.OnExport();\n }\n\n /**\n * Columns to export — from grid state, else the view's columns, else the entity's real fields. Each\n * column carries its field's export type, as the grid's export does, so a date-only field writes\n * a date cell on its stored day rather than a timestamp.\n */\n private buildExportColumns(): ExportColumn[] {\n if (!this.EntityInfo) return [];\n const entity = this.EntityInfo;\n const typed = (name: string, displayName: string): ExportColumn => {\n const field = entity.Fields.find(f => f.Name.toLowerCase() === name.toLowerCase());\n return { name, displayName, dataType: ExportColumnTypeForSQLType(field?.Type) };\n };\n if (this.GridState?.columnSettings && this.GridState.columnSettings.length > 0) {\n return this.GridState.columnSettings\n .filter(col => col.hidden !== true)\n .map(col => typed(col.Name, col.DisplayName || col.Name));\n }\n if (this.ViewEntity?.Columns) {\n return this.ViewEntity.Columns\n .filter(col => !col.hidden)\n .map(col => typed(col.Name, col.DisplayName || col.Name));\n }\n return entity.Fields\n .filter(f => !f.IsVirtual)\n .map(f => typed(f.Name, f.DisplayNameOrName));\n }\n\n private buildExportFileName(): string {\n const viewName = this.ViewEntity?.Name || 'Data';\n return `${this.EntityInfo!.Name}_${viewName}_${new Date().toISOString().split('T')[0]}`;\n }\n\n /**\n * Get display name for the resource tab\n */\n override async GetResourceDisplayName(data: ResourceData): Promise<string> {\n if (data.ResourceRecordID) {\n const compositeKey = CompositeKey.FromID(data.ResourceRecordID); // first-pk-ok: ResourceRecordID of a User Views resource — core entity keyed by ID\n const name = await this.metadata.GetEntityRecordName('MJ: User Views', compositeKey);\n return name ? name : `View: ${data.ResourceRecordID}`;\n }\n else if (data.Configuration?.Entity) {\n const entityName = data.Configuration.Entity as string;\n const hasFilter = data.Configuration.ExtraFilter;\n return `${entityName} [Dynamic${hasFilter ? ' - Filtered' : ' - All'}]`;\n }\n return 'User Views [Error]';\n }\n\n /**\n * Get icon class for the resource tab\n */\n override async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-table-list';\n }\n\n /**\n * Handle creating a new record for the current entity\n */\n public OnCreateNewRecord(): void {\n if (!this.EntityInfo) return;\n\n // Use NavigationService to open a new record form\n this.navigationService.OpenNewEntityRecord(this.EntityInfo.Name);\n }\n\n /** @deprecated Use {@link OnCreateNewRecord}. */\n public onCreateNewRecord(): void {\n return this.OnCreateNewRecord();\n }\n\n /**\n * Open the Save-as-List dialog. Only meaningful for saved views (a\n * ViewID is required to materialize). Dynamic views fall back to a\n * user-visible notification rather than silently doing nothing.\n */\n public OnSaveAsList(): void {\n if (!this.ViewEntity?.ID) {\n this.showNotification('Save as List requires a saved View. Save this view first.', 'info', 4000);\n return;\n }\n // Best-effort record-count hint — the entity-viewer exposes the\n // grid's row count on its gridState; we surface it so the dialog's\n // confirm button can say \"Save List (476 records)\".\n this.SaveAsListRecordCount = this.EntityViewerRef?.TotalRecordCount ?? null;\n this.SaveAsListDialogVisible = true;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link OnSaveAsList}. */\n public onSaveAsList(): void {\n return this.OnSaveAsList();\n }\n\n public OnSaveAsListCancelled(): void {\n this.SaveAsListDialogVisible = false;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link OnSaveAsListCancelled}. */\n public onSaveAsListCancelled(): void {\n return this.OnSaveAsListCancelled();\n }\n\n public async OnSaveAsListSubmit(payload: SaveViewAsListResult): Promise<void> {\n const viewId = this.ViewEntity?.ID;\n if (!viewId) return;\n this.IsSavingAsList = true;\n this.cdr.detectChanges();\n try {\n const provider = this.ProviderToUse as unknown as GraphQLDataProvider;\n const client = new GraphQLListsClient(provider);\n const result = await client.MaterializeFromView(viewId, {\n ListName: payload.ListName,\n Description: payload.Description,\n CategoryId: payload.CategoryId,\n RememberLineage: payload.RememberLineage,\n UseSnapshot: payload.UseSnapshot,\n RefreshMode: payload.RefreshMode,\n });\n if (result.Success && result.CreatedListId) {\n this.SaveAsListDialogVisible = false;\n this.showNotification(\n `List created with ${result.Counts?.Added ?? 0} record(s).`,\n 'success',\n 3000,\n );\n this.navigationService.OpenEntityRecord('MJ: Lists', CompositeKey.FromID(result.CreatedListId));\n } else {\n this.showNotification(`Save failed: ${result.Message}`, 'error', 5000);\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n this.showNotification(`Save failed: ${message}`, 'error', 5000);\n } finally {\n this.IsSavingAsList = false;\n this.cdr.detectChanges();\n }\n }\n\n /** @deprecated Use {@link OnSaveAsListSubmit}. */\n public async onSaveAsListSubmit(payload: SaveViewAsListResult): Promise<void> {\n return this.OnSaveAsListSubmit(payload);\n }\n\n\n /**\n * Show a notification to the user\n */\n private showNotification(message: string, style: 'info' | 'success' | 'error' | 'warning', duration: number): void {\n MJGlobal.Instance.RaiseEvent({\n component: this,\n event: MJEventType.DisplaySimpleNotificationRequest,\n eventCode: '',\n args: {\n message,\n style,\n DisplayDuration: duration\n }\n });\n }\n}\n","<div #container class=\"view-resource-container\">\n @if (isLoading) {\n <div class=\"view-loading-state\">\n <mj-loading text=\"Loading view...\" size=\"large\"></mj-loading>\n </div>\n } @else if (errorMessage) {\n <div class=\"view-error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ errorMessage }}</p>\n </div>\n } @else if (entityInfo) {\n <!-- Header with title and action buttons -->\n <div class=\"view-header\">\n <div class=\"header-left\">\n <h2 class=\"view-title\">{{ viewEntity?.Name || entityInfo.Name }}</h2>\n @if (viewEntity?.Description) {\n <p class=\"view-description\">{{ viewEntity!.Description }}</p>\n }\n </div>\n <div class=\"header-right\">\n <!-- Create New Record Button -->\n <button\n class=\"action-button create-button\"\n (click)=\"onCreateNewRecord()\"\n title=\"Create new {{ entityInfo.Name }} record\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New Record</span>\n </button>\n\n <!-- Save as List Button — only meaningful for saved (non-dynamic) views. -->\n @if (viewEntity?.ID) {\n <button\n class=\"action-button save-as-list-button\"\n (click)=\"onSaveAsList()\"\n [disabled]=\"isSavingAsList\"\n title=\"Materialize these results as a static List\">\n @if (isSavingAsList) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i>\n }\n <span>{{ isSavingAsList ? 'Saving...' : 'Save as List' }}</span>\n </button>\n }\n <!-- Fallback Export button. Shown ONLY for view types that lack their own export UI\n (Cards / Map / Timeline). The Grid renderer has its own in-toolbar Export (full\n result set + format/sampling dialog), so this is suppressed there to avoid a\n duplicate/confusing second button. -->\n @if (showFallbackExportButton) {\n <button\n class=\"action-button export-button\"\n (click)=\"onExport()\"\n [disabled]=\"isExporting\"\n title=\"Export\">\n @if (isExporting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-file-excel\"></i>\n }\n <span>{{ isExporting ? 'Exporting...' : 'Export' }}</span>\n </button>\n }\n </div>\n </div>\n\n <!-- Entity Viewer -->\n <mj-entity-viewer\n #entityViewer\n [Entity]=\"entityInfo\"\n [Provider]=\"Provider\"\n [ViewEntity]=\"viewEntity\"\n [GridState]=\"gridState\"\n [AutoSaveView]=\"true\"\n (RecordOpened)=\"onRecordOpened($any($event))\"\n (OpenRelatedRecordRequested)=\"onOpenRelatedRecord($event)\"\n (AfterViewTypeChange)=\"onViewTypeChanged()\"\n (DataLoaded)=\"onDataLoaded()\">\n </mj-entity-viewer>\n\n <!-- Save-as-List dialog -->\n <mj-save-view-as-list-dialog\n [Provider]=\"ProviderToUse\"\n [Visible]=\"saveAsListDialogVisible\"\n [ViewId]=\"viewEntity?.ID ?? null\"\n [ViewName]=\"viewEntity?.Name ?? null\"\n [RecordCount]=\"saveAsListRecordCount\"\n (Save)=\"onSaveAsListSubmit($event)\"\n (Cancel)=\"onSaveAsListCancelled()\">\n </mj-save-view-as-list-dialog>\n }\n</div>\n"]}
1
+ {"version":3,"file":"view-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/view-resource.component.ts","../../../src/lib/resource-wrappers/view-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ViewChild, ElementRef, ChangeDetectorRef, OnInit, inject } from '@angular/core';\nimport { BaseResourceComponent, NavigationService, SafeDetectChanges } from '@memberjunction/ng-shared';\nimport { ResourceData, MJUserViewEntityExtended, ViewInfo } from '@memberjunction/core-entities';\nimport { RegisterClass, MJGlobal, MJEventType , UUIDsEqual } from '@memberjunction/global';\nimport { CompositeKey, Metadata, EntityInfo, BaseEntity, BaseEntityEvent, LogError } from '@memberjunction/core';\nimport { FormResolverService } from '@memberjunction/ng-base-forms';\nimport { RecordOpenedEvent, ViewGridState, EntityViewerComponent, ViewRelatedRecordNavigation, ExportColumnTypeForSQLType } from '@memberjunction/ng-entity-viewer';\nimport { ExportService } from '@memberjunction/ng-export-service';\nimport { ExportColumn } from '@memberjunction/export-engine';\nimport { GraphQLDataProvider, GraphQLListsClient } from '@memberjunction/graphql-dataprovider';\nimport type { SaveViewAsListResult } from '@memberjunction/ng-list-management';\nimport { ShouldOfferStandardFormCreate } from './standard-form-create';\nimport { debounceTime, filter, takeUntil } from 'rxjs/operators';\n/**\n * UserViewResource - Resource wrapper for displaying User Views in tabs\n *\n * This component wraps the EntityViewerComponent to display view data.\n * It loads the view configuration and entity, then renders the data grid/cards.\n *\n * Key features:\n * - Loads view by ID from ResourceRecordID\n * - Supports dynamic views by entity name + extra filter\n * - Applies view's WhereClause, GridState, and SortState\n * - Opens records in new tabs via NavigationService\n */\n@RegisterClass(BaseResourceComponent, 'ViewResource')\n@Component({\n standalone: false,\n selector: 'mj-userview-resource',\n templateUrl: './view-resource.component.html',\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .view-resource-container {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n .view-header {\n padding: 16px 20px 8px 20px;\n flex-shrink: 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n }\n .header-left {\n flex: 1;\n min-width: 0;\n }\n .header-right {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n }\n .view-title {\n margin: 0 0 4px 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--text-primary, #1a1a1a);\n }\n .view-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--text-secondary, #666);\n }\n .action-button {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n }\n .action-button:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n }\n .action-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .action-button i {\n font-size: 0.875rem;\n }\n .create-button {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n }\n .create-button:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n }\n .export-button:hover:not(:disabled) {\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n }\n .view-loading-state,\n .view-error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n }\n .view-error-state {\n color: var(--danger-color, #dc3545);\n }\n .view-error-state i {\n font-size: 2rem;\n }\n .view-error-state p {\n margin: 0;\n font-size: 1rem;\n }\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n `]\n})\nexport class UserViewResource extends BaseResourceComponent {\n @ViewChild('container', { static: true }) ContainerElement!: ElementRef<HTMLDivElement>;\n\n /** @deprecated Use {@link ContainerElement}. */\n get containerElement(): ElementRef<HTMLDivElement> {\n return this.ContainerElement;\n }\n /** @deprecated Use {@link ContainerElement}. */\n set containerElement(value: ElementRef<HTMLDivElement>) {\n this.ContainerElement = value;\n }\n @ViewChild('entityViewer') EntityViewerRef?: EntityViewerComponent;\n\n /** @deprecated Use {@link EntityViewerRef}. */\n get entityViewerRef(): EntityViewerComponent | undefined {\n return this.EntityViewerRef;\n }\n /** @deprecated Use {@link EntityViewerRef}. */\n set entityViewerRef(value: EntityViewerComponent | undefined) {\n this.EntityViewerRef = value;\n }\n\n public isLoading: boolean = false;\n public errorMessage: string | null = null;\n public EntityInfo: EntityInfo | null = null;\n\n /** @deprecated Use {@link EntityInfo}. */\n public get entityInfo(): EntityInfo | null {\n return this.EntityInfo;\n }\n /** @deprecated Use {@link EntityInfo}. */\n public set entityInfo(value: EntityInfo | null) {\n this.EntityInfo = value;\n }\n public ViewEntity: MJUserViewEntityExtended | null = null;\n\n /**\n * Show \"New in standard form\" (MJ#4755): a custom form hides the CodeGen\n * form for this entity and the user may create. Resolved after load.\n */\n public ShowNewInStandardForm = false;\n\n /** @deprecated Use {@link ViewEntity}. */\n public get viewEntity(): MJUserViewEntityExtended | null {\n return this.ViewEntity;\n }\n /** @deprecated Use {@link ViewEntity}. */\n public set viewEntity(value: MJUserViewEntityExtended | null) {\n this.ViewEntity = value;\n }\n public GridState: ViewGridState | null = null;\n public AlternateBaseView: string | null = null;\n\n /** @deprecated Use {@link GridState}. */\n public get gridState(): ViewGridState | null {\n return this.GridState;\n }\n /** @deprecated Use {@link GridState}. */\n public set gridState(value: ViewGridState | null) {\n this.GridState = value;\n }\n\n // Export state. The header Export button is a FALLBACK shown only for view types that don't\n // provide their own export UI (Cards / Map / Timeline). The Grid renderer has its own in-toolbar\n // Export (full result set + format/sampling dialog), so we suppress this one there to avoid a\n // duplicate/confusing second button — while keeping export available for every other view type.\n public IsExporting: boolean = false;\n\n /** @deprecated Use {@link IsExporting}. */\n public get isExporting(): boolean {\n return this.IsExporting;\n }\n /** @deprecated Use {@link IsExporting}. */\n public set isExporting(value: boolean) {\n this.IsExporting = value;\n }\n public ShowFallbackExportButton: boolean = false;\n\n /** @deprecated Use {@link ShowFallbackExportButton}. */\n public get showFallbackExportButton(): boolean {\n return this.ShowFallbackExportButton;\n }\n /** @deprecated Use {@link ShowFallbackExportButton}. */\n public set showFallbackExportButton(value: boolean) {\n this.ShowFallbackExportButton = value;\n }\n\n // Save-as-list dialog state\n public SaveAsListDialogVisible = false;\n\n /** @deprecated Use {@link SaveAsListDialogVisible}. */\n public get saveAsListDialogVisible() {\n return this.SaveAsListDialogVisible;\n }\n /** @deprecated Use {@link SaveAsListDialogVisible}. */\n public set saveAsListDialogVisible(value) {\n this.SaveAsListDialogVisible = value;\n }\n public SaveAsListRecordCount: number | null = null;\n\n /** @deprecated Use {@link SaveAsListRecordCount}. */\n public get saveAsListRecordCount(): number | null {\n return this.SaveAsListRecordCount;\n }\n /** @deprecated Use {@link SaveAsListRecordCount}. */\n public set saveAsListRecordCount(value: number | null) {\n this.SaveAsListRecordCount = value;\n }\n public IsSavingAsList = false;\n\n /** @deprecated Use {@link IsSavingAsList}. */\n public get isSavingAsList() {\n return this.IsSavingAsList;\n }\n /** @deprecated Use {@link IsSavingAsList}. */\n public set isSavingAsList(value) {\n this.IsSavingAsList = value;\n }\n\n private dataLoaded = false;\n private formResolver = inject(FormResolverService);\n private get metadata() { return this.ProviderToUse; }\n constructor(\n private cdr: ChangeDetectorRef,\n private exportService: ExportService\n ) {\n super();\n }\n\n public override ngOnInit(): void {\n super.ngOnInit();\n\n // Refresh when rows of this view's entity change: a local save/delete, or a server-side\n // write announced as remote-invalidate (a clone, or another server). Debounced, so a burst\n // of writes (a clone creating many rows) reloads the view once.\n MJGlobal.Instance.GetEventListener()\n .pipe(\n filter((event) => {\n if (event.event !== MJEventType.ComponentEvent || event.eventCode !== BaseEntity.BaseEventCode) return false;\n const entityEvent = event.args as BaseEntityEvent;\n const type = entityEvent?.type;\n if (type !== 'save' && type !== 'delete' && type !== 'remote-invalidate') return false;\n const affectedName = (entityEvent.baseEntity?.EntityInfo?.Name ?? entityEvent.entityName)?.trim().toLowerCase();\n return !!affectedName && affectedName === this.entityInfo?.Name?.trim().toLowerCase();\n }),\n debounceTime(300),\n takeUntil(this.destroy$)\n )\n // In place: a change made elsewhere shouldn't move the user off their page or sort.\n .subscribe(() => this.entityViewerRef?.RefreshInPlace());\n }\n\n override set Data(value: ResourceData) {\n const previousRecordId = super.Data?.ResourceRecordID;\n const previousEntity = super.Data?.Configuration?.Entity;\n const previousAbv = super.Data?.Configuration?.AlternateBaseView;\n super.Data = value;\n\n const newRecordId = value?.ResourceRecordID;\n const newEntity = value?.Configuration?.Entity;\n const newAbv = value?.Configuration?.AlternateBaseView;\n\n // View-type (grid/cards/timeline/map) and per-view-type config are now resolved\n // internally by mj-entity-viewer from the saved view's ViewTypeID — nothing to read here.\n\n // Load on first set, or when the view/entity/alternateBaseView has changed\n if (!this.dataLoaded || newRecordId !== previousRecordId || newEntity !== previousEntity || newAbv !== previousAbv) {\n this.dataLoaded = true;\n // Reset state before loading new view\n this.EntityInfo = null;\n this.ViewEntity = null;\n this.GridState = null;\n this.AlternateBaseView = null;\n this.errorMessage = null;\n this.ShowNewInStandardForm = false;\n this.loadView();\n }\n }\n\n override get Data(): ResourceData {\n return super.Data;\n }\n\n /**\n * Load the view and entity based on ResourceData\n */\n private async loadView(): Promise<void> {\n const data = this.Data;\n\n if (!data) {\n this.NotifyLoadComplete();\n return;\n }\n\n this.isLoading = true;\n this.errorMessage = null;\n this.NotifyLoadStarted();\n this.cdr.detectChanges();\n\n try {\n // NavigationService.OpenDynamicView stamps the special marker 'dynamic' as the\n // record ID (tabs require ResourceRecordId) — that is NOT a saved-view ID.\n const recordId = data.ResourceRecordID;\n const isDynamicMarker = typeof recordId === 'string' && recordId.trim().toLowerCase() === 'dynamic';\n // Case 1: Load view by ID\n if (recordId && !isDynamicMarker) {\n await this.loadViewById(recordId);\n }\n // Case 2: Load dynamic view by entity name\n else if (data.Configuration?.Entity) {\n await this.loadDynamicView(\n data.Configuration.Entity as string,\n data.Configuration.ExtraFilter as string | undefined,\n data.Configuration.AlternateBaseView as string | undefined\n );\n }\n else {\n this.errorMessage = 'No view ID or entity specified';\n }\n // Deliberately not awaited: the extra button must never hold up the view.\n void this.refreshStandardFormCreate();\n } catch (error) {\n console.error('Error loading view:', error);\n this.errorMessage = error instanceof Error ? error.message : 'Failed to load view';\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n\n // If there was an error, notify load complete now\n if (this.errorMessage) {\n this.NotifyLoadComplete();\n }\n // Otherwise, wait for dataLoaded event from entity-viewer\n }\n }\n\n /**\n * Load a saved view by its ID\n */\n private async loadViewById(viewId: string): Promise<void> {\n // Load the view entity\n const view = await ViewInfo.GetViewEntity(viewId);\n\n if (!view) {\n throw new Error(`View with ID ${viewId} not found`);\n }\n\n this.ViewEntity = view as MJUserViewEntityExtended;\n\n // Check permissions\n if (!this.ViewEntity.UserCanView) {\n throw new Error('You do not have permission to view this view');\n }\n\n // Load the entity info\n const entity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, this.ViewEntity!.EntityID));\n\n if (!entity) {\n throw new Error(`Entity for view not found`);\n }\n\n this.EntityInfo = entity;\n\n // Parse grid state if available\n if (this.ViewEntity.GridState) {\n try {\n this.GridState = JSON.parse(this.ViewEntity.GridState) as ViewGridState;\n } catch (e) {\n console.warn('Failed to parse GridState:', e);\n this.GridState = null;\n }\n }\n\n // View-type + per-view-type config persistence is fully owned by mj-entity-viewer\n // (it reads ViewTypeID + DisplayState.viewTypeConfigs off the [viewEntity] and, with\n // [AutoSaveView]=\"true\", saves changes back) — nothing to wire here.\n }\n\n /**\n * Load a dynamic view (no saved view, just entity + filter + optional alternate base view)\n */\n private async loadDynamicView(entityName: string, _extraFilter?: string, alternateBaseView?: string): Promise<void> {\n const entity = this.metadata.Entities.find(\n e => e.Name.trim().toLowerCase() === entityName.trim().toLowerCase()\n );\n\n if (!entity) {\n throw new Error(`Entity '${entityName}' not found`);\n }\n\n this.EntityInfo = entity;\n this.ViewEntity = null;\n this.GridState = null;\n this.AlternateBaseView = alternateBaseView || null;\n\n // For dynamic views, we could create a synthetic viewEntity with just the WhereClause\n // but for now, we'll rely on the entity-viewer's default behavior\n }\n\n /**\n * Handle record opened event - open in new tab\n */\n public OnRecordOpened(event: RecordOpenedEvent): void {\n if (event && event.entity && event.compositeKey) {\n this.navigationService.OpenEntityRecord(event.entity.Name, event.compositeKey);\n }\n }\n\n /** @deprecated Use {@link OnRecordOpened}. */\n public onRecordOpened(event: RecordOpenedEvent): void {\n return this.OnRecordOpened(event);\n }\n\n /**\n * Handle a related-record navigation requested from within a view-type renderer\n * (e.g. a foreign-key cell) - open the target record in a new tab.\n */\n public OnOpenRelatedRecord(nav: ViewRelatedRecordNavigation): void {\n if (nav?.entityName && nav.recordKey != null) {\n // The related entity is arbitrary, so its key column can have any name — resolve the key\n // against its metadata rather than hardcoding `ID` via FromID.\n const entityInfo = this.metadata.EntityByName(nav.entityName);\n this.navigationService.OpenEntityRecord(nav.entityName, CompositeKey.FromURLSegment(entityInfo, String(nav.recordKey)));\n }\n }\n\n /** @deprecated Use {@link OnOpenRelatedRecord}. */\n public onOpenRelatedRecord(nav: ViewRelatedRecordNavigation): void {\n return this.OnOpenRelatedRecord(nav);\n }\n\n /**\n * Handle data loaded event from entity-viewer\n */\n public OnDataLoaded(): void {\n this.NotifyLoadComplete();\n this.refreshFallbackExportVisibility();\n }\n\n /** @deprecated Use {@link OnDataLoaded}. */\n public onDataLoaded(): void {\n return this.OnDataLoaded();\n }\n\n /** The active view type changed — recompute whether the fallback Export button is needed. */\n public OnViewTypeChanged(): void {\n this.refreshFallbackExportVisibility();\n }\n\n /** @deprecated Use {@link OnViewTypeChanged}. */\n public onViewTypeChanged(): void {\n return this.OnViewTypeChanged();\n }\n\n /**\n * Show the wrapper's Export button only for view types that don't ship their own export UI. The\n * entity-viewer reports this via {@link EntityViewerComponent.ActiveViewTypeHasOwnExport} (true for\n * the Grid renderer, false for Cards / Map / Timeline). Uses a cached flag + explicit change\n * detection to avoid an ExpressionChanged error from reading child state during a CD pass.\n */\n private refreshFallbackExportVisibility(): void {\n const next = !!this.EntityViewerRef && !this.EntityViewerRef.ActiveViewTypeHasOwnExport;\n if (next !== this.ShowFallbackExportButton) {\n this.ShowFallbackExportButton = next;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Fallback export for view types without their own export UI (Cards / Map / Timeline). Pulls the\n * FULL result set via the entity-viewer's capped, filter/sort-aware fetch (same path the grid uses,\n * so it's bounded and warns past the cap) and writes an Excel file.\n */\n public async OnExport(): Promise<void> {\n // Never fail silently — a \"nothing happens\" click is impossible to diagnose. Surface the\n // reason both in the UI and the console.\n if (!this.EntityInfo || !this.EntityViewerRef) {\n console.error('[ViewResource] Export: viewer not ready', {\n hasEntity: !!this.EntityInfo, hasViewer: !!this.EntityViewerRef\n });\n this.showNotification('Export is not ready yet — try again in a moment.', 'error', 5000);\n return;\n }\n this.IsExporting = true;\n this.cdr.detectChanges();\n this.showNotification('Preparing your Excel export…', 'info', 2000);\n try {\n const rows = await this.EntityViewerRef.FetchAllRowsForExport();\n if (!rows || rows.length === 0) {\n this.showNotification('Nothing to export — the view returned no records.', 'warning', 5000);\n return;\n }\n const result = await this.exportService.toExcel(rows, {\n fileName: this.buildExportFileName(),\n columns: this.buildExportColumns(),\n includeHeaders: true\n });\n if (result.success) {\n this.exportService.downloadResult(result);\n this.showNotification(`Exported ${rows.length.toLocaleString()} record(s) to Excel.`, 'success', 3000);\n } else {\n this.showNotification('Export failed while building the file.', 'error', 5000);\n console.error('[ViewResource] Export: toExcel returned failure', result);\n }\n } catch (e) {\n this.showNotification('Error exporting data — see console for details.', 'error', 5000);\n console.error('[ViewResource] Export error:', e);\n } finally {\n this.IsExporting = false;\n this.cdr.detectChanges();\n }\n }\n\n /** @deprecated Use {@link OnExport}. */\n public async onExport(): Promise<void> {\n return this.OnExport();\n }\n\n /**\n * Columns to export — from grid state, else the view's columns, else the entity's real fields. Each\n * column carries its field's export type, as the grid's export does, so a date-only field writes\n * a date cell on its stored day rather than a timestamp.\n */\n private buildExportColumns(): ExportColumn[] {\n if (!this.EntityInfo) return [];\n const entity = this.EntityInfo;\n const typed = (name: string, displayName: string): ExportColumn => {\n const field = entity.Fields.find(f => f.Name.toLowerCase() === name.toLowerCase());\n return { name, displayName, dataType: ExportColumnTypeForSQLType(field?.Type) };\n };\n if (this.GridState?.columnSettings && this.GridState.columnSettings.length > 0) {\n return this.GridState.columnSettings\n .filter(col => col.hidden !== true)\n .map(col => typed(col.Name, col.DisplayName || col.Name));\n }\n if (this.ViewEntity?.Columns) {\n return this.ViewEntity.Columns\n .filter(col => !col.hidden)\n .map(col => typed(col.Name, col.DisplayName || col.Name));\n }\n return entity.Fields\n .filter(f => !f.IsVirtual)\n .map(f => typed(f.Name, f.DisplayNameOrName));\n }\n\n private buildExportFileName(): string {\n const viewName = this.ViewEntity?.Name || 'Data';\n return `${this.EntityInfo!.Name}_${viewName}_${new Date().toISOString().split('T')[0]}`;\n }\n\n /**\n * Get display name for the resource tab\n */\n override async GetResourceDisplayName(data: ResourceData): Promise<string> {\n if (data.ResourceRecordID) {\n const compositeKey = CompositeKey.FromID(data.ResourceRecordID); // first-pk-ok: ResourceRecordID of a User Views resource — core entity keyed by ID\n const name = await this.metadata.GetEntityRecordName('MJ: User Views', compositeKey);\n return name ? name : `View: ${data.ResourceRecordID}`;\n }\n else if (data.Configuration?.Entity) {\n const entityName = data.Configuration.Entity as string;\n const hasFilter = data.Configuration.ExtraFilter;\n return `${entityName} [Dynamic${hasFilter ? ' - Filtered' : ' - All'}]`;\n }\n return 'User Views [Error]';\n }\n\n /**\n * Get icon class for the resource tab\n */\n override async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-table-list';\n }\n\n /**\n * Handle creating a new record for the current entity\n */\n public OnCreateNewRecord(): void {\n if (!this.EntityInfo) return;\n\n // Use NavigationService to open a new record form\n this.navigationService.OpenNewEntityRecord(this.EntityInfo.Name);\n }\n\n /** @deprecated Use {@link OnCreateNewRecord}. */\n public onCreateNewRecord(): void {\n return this.OnCreateNewRecord();\n }\n\n /**\n * Create a new record in the CodeGen standard form (MJ#4755) — the escape\n * hatch for entities whose custom form cannot create records.\n */\n public OnCreateNewRecordInStandardForm(): void {\n if (!this.EntityInfo) return;\n this.navigationService.OpenNewEntityRecord(this.EntityInfo.Name, { formMode: 'standard' });\n }\n\n /**\n * Decide whether to offer \"New in standard form\" for the loaded entity.\n * Discards the answer if the view moved to another entity meanwhile.\n */\n private async refreshStandardFormCreate(): Promise<void> {\n const entity = this.EntityInfo;\n if (!entity) return;\n let show = false;\n try {\n const p = this.ProviderToUse;\n const res = await this.formResolver.ResolveFormForEntity(entity, p.CurrentUser, p);\n const canCreate = entity.GetUserPermisions(p.CurrentUser).CanCreate;\n show = ShouldOfferStandardFormCreate(res, canCreate);\n } catch (err) {\n LogError(`ViewResource: could not resolve forms for \"${entity.Name}\": ${err instanceof Error ? err.message : String(err)}`);\n }\n if (this.EntityInfo !== entity) return;\n this.ShowNewInStandardForm = show;\n // Safe variant: this runs after an await in a fire-and-forget promise,\n // so the view may be destroyed (tab closed) or mid-pass by now.\n SafeDetectChanges(this.cdr);\n }\n\n /**\n * Open the Save-as-List dialog. Only meaningful for saved views (a\n * ViewID is required to materialize). Dynamic views fall back to a\n * user-visible notification rather than silently doing nothing.\n */\n public OnSaveAsList(): void {\n if (!this.ViewEntity?.ID) {\n this.showNotification('Save as List requires a saved View. Save this view first.', 'info', 4000);\n return;\n }\n // Best-effort record-count hint — the entity-viewer exposes the\n // grid's row count on its gridState; we surface it so the dialog's\n // confirm button can say \"Save List (476 records)\".\n this.SaveAsListRecordCount = this.EntityViewerRef?.TotalRecordCount ?? null;\n this.SaveAsListDialogVisible = true;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link OnSaveAsList}. */\n public onSaveAsList(): void {\n return this.OnSaveAsList();\n }\n\n public OnSaveAsListCancelled(): void {\n this.SaveAsListDialogVisible = false;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link OnSaveAsListCancelled}. */\n public onSaveAsListCancelled(): void {\n return this.OnSaveAsListCancelled();\n }\n\n public async OnSaveAsListSubmit(payload: SaveViewAsListResult): Promise<void> {\n const viewId = this.ViewEntity?.ID;\n if (!viewId) return;\n this.IsSavingAsList = true;\n this.cdr.detectChanges();\n try {\n const provider = this.ProviderToUse as unknown as GraphQLDataProvider;\n const client = new GraphQLListsClient(provider);\n const result = await client.MaterializeFromView(viewId, {\n ListName: payload.ListName,\n Description: payload.Description,\n CategoryId: payload.CategoryId,\n RememberLineage: payload.RememberLineage,\n UseSnapshot: payload.UseSnapshot,\n RefreshMode: payload.RefreshMode,\n });\n if (result.Success && result.CreatedListId) {\n this.SaveAsListDialogVisible = false;\n this.showNotification(\n `List created with ${result.Counts?.Added ?? 0} record(s).`,\n 'success',\n 3000,\n );\n this.navigationService.OpenEntityRecord('MJ: Lists', CompositeKey.FromID(result.CreatedListId));\n } else {\n this.showNotification(`Save failed: ${result.Message}`, 'error', 5000);\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n this.showNotification(`Save failed: ${message}`, 'error', 5000);\n } finally {\n this.IsSavingAsList = false;\n this.cdr.detectChanges();\n }\n }\n\n /** @deprecated Use {@link OnSaveAsListSubmit}. */\n public async onSaveAsListSubmit(payload: SaveViewAsListResult): Promise<void> {\n return this.OnSaveAsListSubmit(payload);\n }\n\n\n /**\n * Show a notification to the user\n */\n private showNotification(message: string, style: 'info' | 'success' | 'error' | 'warning', duration: number): void {\n MJGlobal.Instance.RaiseEvent({\n component: this,\n event: MJEventType.DisplaySimpleNotificationRequest,\n eventCode: '',\n args: {\n message,\n style,\n DisplayDuration: duration\n }\n });\n }\n}\n","<div #container class=\"view-resource-container\">\n @if (isLoading) {\n <div class=\"view-loading-state\">\n <mj-loading text=\"Loading view...\" size=\"large\"></mj-loading>\n </div>\n } @else if (errorMessage) {\n <div class=\"view-error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ errorMessage }}</p>\n </div>\n } @else if (entityInfo) {\n <!-- Header with title and action buttons -->\n <div class=\"view-header\">\n <div class=\"header-left\">\n <h2 class=\"view-title\">{{ viewEntity?.Name || entityInfo.Name }}</h2>\n @if (viewEntity?.Description) {\n <p class=\"view-description\">{{ viewEntity!.Description }}</p>\n }\n </div>\n <div class=\"header-right\">\n <!-- Create New Record Button -->\n <button\n class=\"action-button create-button\"\n (click)=\"onCreateNewRecord()\"\n title=\"Create new {{ entityInfo.Name }} record\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New Record</span>\n </button>\n\n <!-- A custom form hides the CodeGen form for this entity (MJ#4755). -->\n @if (ShowNewInStandardForm) {\n <button mjButton Variant=\"outline\" type=\"button\" class=\"action-button\"\n (click)=\"OnCreateNewRecordInStandardForm()\"\n title=\"Create a new {{ entityInfo.Name }} record in the standard form (all form fields)\">\n <i class=\"fa-solid fa-table-list\" aria-hidden=\"true\"></i>\n <span>New in standard form</span>\n </button>\n }\n\n <!-- Save as List Button — only meaningful for saved (non-dynamic) views. -->\n @if (viewEntity?.ID) {\n <button\n class=\"action-button save-as-list-button\"\n (click)=\"onSaveAsList()\"\n [disabled]=\"isSavingAsList\"\n title=\"Materialize these results as a static List\">\n @if (isSavingAsList) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i>\n }\n <span>{{ isSavingAsList ? 'Saving...' : 'Save as List' }}</span>\n </button>\n }\n <!-- Fallback Export button. Shown ONLY for view types that lack their own export UI\n (Cards / Map / Timeline). The Grid renderer has its own in-toolbar Export (full\n result set + format/sampling dialog), so this is suppressed there to avoid a\n duplicate/confusing second button. -->\n @if (showFallbackExportButton) {\n <button\n class=\"action-button export-button\"\n (click)=\"onExport()\"\n [disabled]=\"isExporting\"\n title=\"Export\">\n @if (isExporting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n } @else {\n <i class=\"fa-solid fa-file-excel\"></i>\n }\n <span>{{ isExporting ? 'Exporting...' : 'Export' }}</span>\n </button>\n }\n </div>\n </div>\n\n <!-- Entity Viewer -->\n <mj-entity-viewer\n #entityViewer\n [Entity]=\"entityInfo\"\n [Provider]=\"Provider\"\n [ViewEntity]=\"viewEntity\"\n [AlternateBaseView]=\"AlternateBaseView\"\n [GridState]=\"gridState\"\n [AutoSaveView]=\"true\"\n (RecordOpened)=\"onRecordOpened($any($event))\"\n (OpenRelatedRecordRequested)=\"onOpenRelatedRecord($event)\"\n (AfterViewTypeChange)=\"onViewTypeChanged()\"\n (DataLoaded)=\"onDataLoaded()\">\n </mj-entity-viewer>\n\n <!-- Save-as-List dialog -->\n <mj-save-view-as-list-dialog\n [Provider]=\"ProviderToUse\"\n [Visible]=\"saveAsListDialogVisible\"\n [ViewId]=\"viewEntity?.ID ?? null\"\n [ViewName]=\"viewEntity?.Name ?? null\"\n [RecordCount]=\"saveAsListRecordCount\"\n (Save)=\"onSaveAsListSubmit($event)\"\n (Cancel)=\"onSaveAsListCancelled()\">\n </mj-save-view-as-list-dialog>\n }\n</div>\n"]}