@memberjunction/ng-entity-viewer 2.132.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +317 -124
- package/dist/lib/entity-cards/entity-cards.component.js +2 -2
- package/dist/lib/entity-cards/entity-cards.component.js.map +1 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts +793 -0
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts.map +1 -0
- package/dist/lib/entity-data-grid/entity-data-grid.component.js +3781 -0
- package/dist/lib/entity-data-grid/entity-data-grid.component.js.map +1 -0
- package/dist/lib/entity-data-grid/events/grid-events.d.ts +398 -0
- package/dist/lib/entity-data-grid/events/grid-events.d.ts.map +1 -0
- package/dist/lib/entity-data-grid/events/grid-events.js +556 -0
- package/dist/lib/entity-data-grid/events/grid-events.js.map +1 -0
- package/dist/lib/entity-data-grid/models/grid-types.d.ts +437 -0
- package/dist/lib/entity-data-grid/models/grid-types.d.ts.map +1 -0
- package/dist/lib/entity-data-grid/models/grid-types.js +37 -0
- package/dist/lib/entity-data-grid/models/grid-types.js.map +1 -0
- package/dist/lib/entity-grid/entity-grid.component.js +1 -1
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js +2 -2
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts +136 -2
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.js +321 -94
- package/dist/lib/entity-viewer/entity-viewer.component.js.map +1 -1
- package/dist/lib/pagination/pagination.component.js +2 -2
- package/dist/lib/pagination/pagination.component.js.map +1 -1
- package/dist/lib/pill/pill.component.js +2 -2
- package/dist/lib/pill/pill.component.js.map +1 -1
- package/dist/lib/types.d.ts +14 -31
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/view-config-panel/view-config-panel.component.d.ts +363 -0
- package/dist/lib/view-config-panel/view-config-panel.component.d.ts.map +1 -0
- package/dist/lib/view-config-panel/view-config-panel.component.js +2006 -0
- package/dist/lib/view-config-panel/view-config-panel.component.js.map +1 -0
- package/dist/module.d.ts +16 -13
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +25 -15
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +4 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +6 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +15 -11
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
3
|
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
|
|
4
4
|
import { EntityFieldTSType, RunView } from '@memberjunction/core';
|
|
5
5
|
import { TimelineGroup } from '@memberjunction/ng-timeline';
|
|
6
6
|
import { DEFAULT_VIEWER_CONFIG } from '../types';
|
|
7
|
+
import { EntityDataGridComponent } from '../entity-data-grid/entity-data-grid.component';
|
|
7
8
|
import * as i0 from "@angular/core";
|
|
8
9
|
import * as i1 from "@angular/forms";
|
|
9
10
|
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
10
11
|
import * as i3 from "@memberjunction/ng-timeline";
|
|
11
|
-
import * as i4 from "../entity-
|
|
12
|
-
import * as i5 from "../
|
|
13
|
-
import * as i6 from "../
|
|
12
|
+
import * as i4 from "../entity-cards/entity-cards.component";
|
|
13
|
+
import * as i5 from "../pagination/pagination.component";
|
|
14
|
+
import * as i6 from "../entity-data-grid/entity-data-grid.component";
|
|
14
15
|
import * as i7 from "@angular/common";
|
|
15
16
|
const _forTrack0 = ($index, $item) => $item.Name;
|
|
16
17
|
function EntityViewerComponent_Conditional_1_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
17
18
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
18
|
-
i0.ɵɵelementStart(0, "button",
|
|
19
|
+
i0.ɵɵelementStart(0, "button", 20);
|
|
19
20
|
i0.ɵɵlistener("click", function EntityViewerComponent_Conditional_1_Conditional_1_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.clearFilter()); });
|
|
20
|
-
i0.ɵɵelement(1, "i",
|
|
21
|
+
i0.ɵɵelement(1, "i", 21);
|
|
21
22
|
i0.ɵɵelementEnd();
|
|
22
23
|
} }
|
|
23
24
|
function EntityViewerComponent_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
24
25
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
25
|
-
i0.ɵɵelementStart(0, "div",
|
|
26
|
-
i0.ɵɵelement(1, "i",
|
|
27
|
-
i0.ɵɵelementStart(2, "input",
|
|
26
|
+
i0.ɵɵelementStart(0, "div", 14);
|
|
27
|
+
i0.ɵɵelement(1, "i", 17);
|
|
28
|
+
i0.ɵɵelementStart(2, "input", 18);
|
|
28
29
|
i0.ɵɵlistener("input", function EntityViewerComponent_Conditional_1_Conditional_1_Template_input_input_2_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onFilterChange($event.target.value)); });
|
|
29
30
|
i0.ɵɵelementEnd();
|
|
30
|
-
i0.ɵɵtemplate(3, EntityViewerComponent_Conditional_1_Conditional_1_Conditional_3_Template, 2, 0, "button",
|
|
31
|
+
i0.ɵɵtemplate(3, EntityViewerComponent_Conditional_1_Conditional_1_Conditional_3_Template, 2, 0, "button", 19);
|
|
31
32
|
i0.ɵɵelementEnd();
|
|
32
33
|
} if (rf & 2) {
|
|
33
34
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -58,7 +59,7 @@ function EntityViewerComponent_Conditional_1_Conditional_2_Conditional_2_Templat
|
|
|
58
59
|
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(2, 1, ctx_r1.totalRecordCount), " records");
|
|
59
60
|
} }
|
|
60
61
|
function EntityViewerComponent_Conditional_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
61
|
-
i0.ɵɵelementStart(0, "div",
|
|
62
|
+
i0.ɵɵelementStart(0, "div", 15);
|
|
62
63
|
i0.ɵɵtemplate(1, EntityViewerComponent_Conditional_1_Conditional_2_Conditional_1_Template, 4, 6, "span")(2, EntityViewerComponent_Conditional_1_Conditional_2_Conditional_2_Template, 3, 3, "span");
|
|
63
64
|
i0.ɵɵelementEnd();
|
|
64
65
|
} if (rf & 2) {
|
|
@@ -68,9 +69,9 @@ function EntityViewerComponent_Conditional_1_Conditional_2_Template(rf, ctx) { i
|
|
|
68
69
|
} }
|
|
69
70
|
function EntityViewerComponent_Conditional_1_Conditional_3_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
70
71
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
71
|
-
i0.ɵɵelementStart(0, "button",
|
|
72
|
+
i0.ɵɵelementStart(0, "button", 27);
|
|
72
73
|
i0.ɵɵlistener("click", function EntityViewerComponent_Conditional_1_Conditional_3_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setViewMode("timeline")); });
|
|
73
|
-
i0.ɵɵelement(1, "i",
|
|
74
|
+
i0.ɵɵelement(1, "i", 28);
|
|
74
75
|
i0.ɵɵelementEnd();
|
|
75
76
|
} if (rf & 2) {
|
|
76
77
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -78,15 +79,15 @@ function EntityViewerComponent_Conditional_1_Conditional_3_Conditional_5_Templat
|
|
|
78
79
|
} }
|
|
79
80
|
function EntityViewerComponent_Conditional_1_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
80
81
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
81
|
-
i0.ɵɵelementStart(0, "div",
|
|
82
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "button", 22);
|
|
82
83
|
i0.ɵɵlistener("click", function EntityViewerComponent_Conditional_1_Conditional_3_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setViewMode("grid")); });
|
|
83
|
-
i0.ɵɵelement(2, "i",
|
|
84
|
+
i0.ɵɵelement(2, "i", 23);
|
|
84
85
|
i0.ɵɵelementEnd();
|
|
85
|
-
i0.ɵɵelementStart(3, "button",
|
|
86
|
+
i0.ɵɵelementStart(3, "button", 24);
|
|
86
87
|
i0.ɵɵlistener("click", function EntityViewerComponent_Conditional_1_Conditional_3_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setViewMode("cards")); });
|
|
87
|
-
i0.ɵɵelement(4, "i",
|
|
88
|
+
i0.ɵɵelement(4, "i", 25);
|
|
88
89
|
i0.ɵɵelementEnd();
|
|
89
|
-
i0.ɵɵtemplate(5, EntityViewerComponent_Conditional_1_Conditional_3_Conditional_5_Template, 2, 2, "button",
|
|
90
|
+
i0.ɵɵtemplate(5, EntityViewerComponent_Conditional_1_Conditional_3_Conditional_5_Template, 2, 2, "button", 26);
|
|
90
91
|
i0.ɵɵelementEnd();
|
|
91
92
|
} if (rf & 2) {
|
|
92
93
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -98,7 +99,7 @@ function EntityViewerComponent_Conditional_1_Conditional_3_Template(rf, ctx) { i
|
|
|
98
99
|
i0.ɵɵconditional(ctx_r1.hasDateFields ? 5 : -1);
|
|
99
100
|
} }
|
|
100
101
|
function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
101
|
-
i0.ɵɵelementStart(0, "span",
|
|
102
|
+
i0.ɵɵelementStart(0, "span", 31);
|
|
102
103
|
i0.ɵɵtext(1);
|
|
103
104
|
i0.ɵɵelementEnd();
|
|
104
105
|
} if (rf & 2) {
|
|
@@ -107,7 +108,7 @@ function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_2_Templat
|
|
|
107
108
|
i0.ɵɵtextInterpolate(ctx_r1.selectedDateFieldDisplayName);
|
|
108
109
|
} }
|
|
109
110
|
function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
110
|
-
i0.ɵɵelementStart(0, "option",
|
|
111
|
+
i0.ɵɵelementStart(0, "option", 37);
|
|
111
112
|
i0.ɵɵtext(1);
|
|
112
113
|
i0.ɵɵelementEnd();
|
|
113
114
|
} if (rf & 2) {
|
|
@@ -118,9 +119,9 @@ function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_For_2_T
|
|
|
118
119
|
} }
|
|
119
120
|
function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
120
121
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
121
|
-
i0.ɵɵelementStart(0, "select",
|
|
122
|
+
i0.ɵɵelementStart(0, "select", 36);
|
|
122
123
|
i0.ɵɵlistener("change", function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_Template_select_change_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.setTimelineDateField($event.target.value)); });
|
|
123
|
-
i0.ɵɵrepeaterCreate(1, EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_For_2_Template, 2, 2, "option",
|
|
124
|
+
i0.ɵɵrepeaterCreate(1, EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_For_2_Template, 2, 2, "option", 37, _forTrack0);
|
|
124
125
|
i0.ɵɵelementEnd();
|
|
125
126
|
} if (rf & 2) {
|
|
126
127
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -130,15 +131,15 @@ function EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_Templat
|
|
|
130
131
|
} }
|
|
131
132
|
function EntityViewerComponent_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
132
133
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
133
|
-
i0.ɵɵelementStart(0, "div",
|
|
134
|
-
i0.ɵɵelement(1, "i",
|
|
135
|
-
i0.ɵɵtemplate(2, EntityViewerComponent_Conditional_1_Conditional_4_Conditional_2_Template, 2, 1, "span",
|
|
134
|
+
i0.ɵɵelementStart(0, "div", 29);
|
|
135
|
+
i0.ɵɵelement(1, "i", 30);
|
|
136
|
+
i0.ɵɵtemplate(2, EntityViewerComponent_Conditional_1_Conditional_4_Conditional_2_Template, 2, 1, "span", 31)(3, EntityViewerComponent_Conditional_1_Conditional_4_Conditional_3_Template, 3, 1, "select", 32);
|
|
136
137
|
i0.ɵɵelementEnd();
|
|
137
|
-
i0.ɵɵelementStart(4, "div",
|
|
138
|
+
i0.ɵɵelementStart(4, "div", 33)(5, "button", 34);
|
|
138
139
|
i0.ɵɵlistener("click", function EntityViewerComponent_Conditional_1_Conditional_4_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleTimelineOrientation()); });
|
|
139
140
|
i0.ɵɵelement(6, "i");
|
|
140
141
|
i0.ɵɵelementEnd()();
|
|
141
|
-
i0.ɵɵelementStart(7, "div",
|
|
142
|
+
i0.ɵɵelementStart(7, "div", 35)(8, "button", 34);
|
|
142
143
|
i0.ɵɵlistener("click", function EntityViewerComponent_Conditional_1_Conditional_4_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleTimelineSortOrder()); });
|
|
143
144
|
i0.ɵɵelement(9, "i");
|
|
144
145
|
i0.ɵɵelementEnd()();
|
|
@@ -157,7 +158,7 @@ function EntityViewerComponent_Conditional_1_Conditional_4_Template(rf, ctx) { i
|
|
|
157
158
|
} }
|
|
158
159
|
function EntityViewerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
159
160
|
i0.ɵɵelementStart(0, "div", 1);
|
|
160
|
-
i0.ɵɵtemplate(1, EntityViewerComponent_Conditional_1_Conditional_1_Template, 4, 3, "div",
|
|
161
|
+
i0.ɵɵtemplate(1, EntityViewerComponent_Conditional_1_Conditional_1_Template, 4, 3, "div", 14)(2, EntityViewerComponent_Conditional_1_Conditional_2_Template, 3, 1, "div", 15)(3, EntityViewerComponent_Conditional_1_Conditional_3_Template, 6, 5, "div", 16)(4, EntityViewerComponent_Conditional_1_Conditional_4_Template, 10, 7);
|
|
161
162
|
i0.ɵɵelementEnd();
|
|
162
163
|
} if (rf & 2) {
|
|
163
164
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -170,63 +171,10 @@ function EntityViewerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
|
170
171
|
i0.ɵɵadvance();
|
|
171
172
|
i0.ɵɵconditional(ctx_r1.effectiveViewMode === "timeline" && ctx_r1.hasDateFields ? 4 : -1);
|
|
172
173
|
} }
|
|
173
|
-
function
|
|
174
|
-
i0.ɵɵelementStart(0, "div", 3);
|
|
175
|
-
i0.ɵɵelement(1, "mj-loading", 30);
|
|
176
|
-
i0.ɵɵelementEnd();
|
|
177
|
-
} if (rf & 2) {
|
|
178
|
-
const ctx_r1 = i0.ɵɵnextContext();
|
|
179
|
-
i0.ɵɵadvance();
|
|
180
|
-
i0.ɵɵproperty("text", ctx_r1.loadingMessage);
|
|
181
|
-
} }
|
|
182
|
-
function EntityViewerComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
183
|
-
i0.ɵɵelementStart(0, "div", 4);
|
|
184
|
-
i0.ɵɵelement(1, "i", 31);
|
|
185
|
-
i0.ɵɵelementStart(2, "p");
|
|
186
|
-
i0.ɵɵtext(3, "Select an entity to view records");
|
|
187
|
-
i0.ɵɵelementEnd()();
|
|
188
|
-
} }
|
|
189
|
-
function EntityViewerComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
190
|
-
i0.ɵɵelementStart(0, "div", 4);
|
|
191
|
-
i0.ɵɵelement(1, "i", 32);
|
|
192
|
-
i0.ɵɵelementStart(2, "p");
|
|
193
|
-
i0.ɵɵtext(3);
|
|
194
|
-
i0.ɵɵelementEnd()();
|
|
195
|
-
} if (rf & 2) {
|
|
196
|
-
const ctx_r1 = i0.ɵɵnextContext();
|
|
197
|
-
i0.ɵɵadvance(3);
|
|
198
|
-
i0.ɵɵtextInterpolate(ctx_r1.debouncedFilterText ? "No matching records" : "No records found");
|
|
199
|
-
} }
|
|
200
|
-
function EntityViewerComponent_Conditional_6_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
201
|
-
const _r10 = i0.ɵɵgetCurrentView();
|
|
202
|
-
i0.ɵɵelementStart(0, "mj-timeline", 36);
|
|
203
|
-
i0.ɵɵlistener("afterEventClick", function EntityViewerComponent_Conditional_6_Conditional_2_Template_mj_timeline_afterEventClick_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onTimelineEventClick($event)); });
|
|
204
|
-
i0.ɵɵelementEnd();
|
|
205
|
-
} if (rf & 2) {
|
|
206
|
-
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
207
|
-
i0.ɵɵproperty("groups", ctx_r1.timelineGroups)("orientation", ctx_r1.timelineOrientation)("layout", ctx_r1.timelineOrientation === "vertical" ? "alternating" : "single")("sortOrder", ctx_r1.timelineSortOrder)("segmentGrouping", ctx_r1.timelineSegmentGrouping)("segmentsCollapsible", true)("segmentsDefaultExpanded", true)("selectedEventId", ctx_r1.timelineSelectedEventId);
|
|
208
|
-
} }
|
|
209
|
-
function EntityViewerComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
174
|
+
function EntityViewerComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
210
175
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
211
|
-
i0.ɵɵelementStart(0, "mj-
|
|
212
|
-
i0.ɵɵlistener("
|
|
213
|
-
i0.ɵɵelementEnd();
|
|
214
|
-
i0.ɵɵelementStart(1, "mj-entity-cards", 34);
|
|
215
|
-
i0.ɵɵlistener("recordSelected", function EntityViewerComponent_Conditional_6_Template_mj_entity_cards_recordSelected_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRecordSelected($event)); })("recordOpened", function EntityViewerComponent_Conditional_6_Template_mj_entity_cards_recordOpened_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRecordOpened($event)); });
|
|
216
|
-
i0.ɵɵelementEnd();
|
|
217
|
-
i0.ɵɵtemplate(2, EntityViewerComponent_Conditional_6_Conditional_2_Template, 1, 8, "mj-timeline", 35);
|
|
218
|
-
} if (rf & 2) {
|
|
219
|
-
const ctx_r1 = i0.ɵɵnextContext();
|
|
220
|
-
i0.ɵɵproperty("hidden", ctx_r1.effectiveViewMode !== "grid")("entity", ctx_r1.entity)("records", ctx_r1.filteredRecords)("selectedRecordId", ctx_r1.selectedRecordId)("columns", ctx_r1.gridColumns)("height", "100%")("filterText", ctx_r1.debouncedFilterText)("sortState", ctx_r1.effectiveSortState)("serverSideSorting", ctx_r1.effectiveConfig.serverSideSorting)("gridState", ctx_r1.gridState);
|
|
221
|
-
i0.ɵɵadvance();
|
|
222
|
-
i0.ɵɵproperty("hidden", ctx_r1.effectiveViewMode !== "cards")("entity", ctx_r1.entity)("records", ctx_r1.filteredRecords)("selectedRecordId", ctx_r1.selectedRecordId)("cardTemplate", ctx_r1.cardTemplate)("hiddenFieldMatches", ctx_r1.hiddenFieldMatches)("filterText", ctx_r1.debouncedFilterText);
|
|
223
|
-
i0.ɵɵadvance();
|
|
224
|
-
i0.ɵɵconditional(ctx_r1.hasDateFields && ctx_r1.effectiveViewMode === "timeline" ? 2 : -1);
|
|
225
|
-
} }
|
|
226
|
-
function EntityViewerComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
-
const _r11 = i0.ɵɵgetCurrentView();
|
|
228
|
-
i0.ɵɵelementStart(0, "mj-pagination", 37);
|
|
229
|
-
i0.ɵɵlistener("loadMore", function EntityViewerComponent_Conditional_7_Template_mj_pagination_loadMore_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onLoadMore()); });
|
|
176
|
+
i0.ɵɵelementStart(0, "mj-pagination", 38);
|
|
177
|
+
i0.ɵɵlistener("loadMore", function EntityViewerComponent_Conditional_18_Template_mj_pagination_loadMore_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onLoadMore()); });
|
|
230
178
|
i0.ɵɵelementEnd();
|
|
231
179
|
} if (rf & 2) {
|
|
232
180
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -344,6 +292,29 @@ export class EntityViewerComponent {
|
|
|
344
292
|
}
|
|
345
293
|
}
|
|
346
294
|
_timelineConfig = null;
|
|
295
|
+
/**
|
|
296
|
+
* Whether to show the grid toolbar.
|
|
297
|
+
* When false, the grid is displayed without its own toolbar - useful when
|
|
298
|
+
* entity-viewer provides its own filter/actions in the header.
|
|
299
|
+
* @default false
|
|
300
|
+
*/
|
|
301
|
+
showGridToolbar = false;
|
|
302
|
+
/**
|
|
303
|
+
* Grid toolbar configuration - controls which buttons are shown and their behavior
|
|
304
|
+
* When not provided, uses sensible defaults
|
|
305
|
+
*/
|
|
306
|
+
gridToolbarConfig = null;
|
|
307
|
+
/**
|
|
308
|
+
* Grid selection mode
|
|
309
|
+
* @default 'single'
|
|
310
|
+
*/
|
|
311
|
+
gridSelectionMode = 'single';
|
|
312
|
+
/**
|
|
313
|
+
* Show the "Add to List" button in the grid toolbar.
|
|
314
|
+
* Requires gridSelectionMode to be 'multiple' for best UX.
|
|
315
|
+
* @default false
|
|
316
|
+
*/
|
|
317
|
+
showAddToListButton = false;
|
|
347
318
|
// ========================================
|
|
348
319
|
// OUTPUTS
|
|
349
320
|
// ========================================
|
|
@@ -383,6 +354,33 @@ export class EntityViewerComponent {
|
|
|
383
354
|
* Emitted when timeline configuration changes (date field, grouping, etc.)
|
|
384
355
|
*/
|
|
385
356
|
timelineConfigChange = new EventEmitter();
|
|
357
|
+
/**
|
|
358
|
+
* Emitted when the Add/New button is clicked in the grid toolbar
|
|
359
|
+
*/
|
|
360
|
+
addRequested = new EventEmitter();
|
|
361
|
+
/**
|
|
362
|
+
* Emitted when the Delete button is clicked in the grid toolbar
|
|
363
|
+
* Includes the selected records to be deleted
|
|
364
|
+
*/
|
|
365
|
+
deleteRequested = new EventEmitter();
|
|
366
|
+
/**
|
|
367
|
+
* Emitted when the Refresh button is clicked in the grid toolbar
|
|
368
|
+
*/
|
|
369
|
+
refreshRequested = new EventEmitter();
|
|
370
|
+
/**
|
|
371
|
+
* Emitted when the Export button is clicked in the grid toolbar
|
|
372
|
+
*/
|
|
373
|
+
exportRequested = new EventEmitter();
|
|
374
|
+
/**
|
|
375
|
+
* Emitted when the Add to List button is clicked in the grid toolbar.
|
|
376
|
+
* Parent components should handle this to show the list management dialog.
|
|
377
|
+
*/
|
|
378
|
+
addToListRequested = new EventEmitter();
|
|
379
|
+
/**
|
|
380
|
+
* Emitted when grid selection changes.
|
|
381
|
+
* Parent components can use this to track selected records for their own toolbar buttons.
|
|
382
|
+
*/
|
|
383
|
+
selectionChanged = new EventEmitter();
|
|
386
384
|
// ========================================
|
|
387
385
|
// INTERNAL STATE
|
|
388
386
|
// ========================================
|
|
@@ -398,6 +396,10 @@ export class EntityViewerComponent {
|
|
|
398
396
|
hiddenFieldMatches = new Map();
|
|
399
397
|
/** Current sort state */
|
|
400
398
|
internalSortState = null;
|
|
399
|
+
/** Cached grid params to avoid recreating object on every change detection */
|
|
400
|
+
_cachedGridParams = null;
|
|
401
|
+
_lastGridParamsEntity = null;
|
|
402
|
+
_lastGridParamsViewEntity = null;
|
|
401
403
|
/** Pagination state */
|
|
402
404
|
pagination = {
|
|
403
405
|
currentPage: 0,
|
|
@@ -443,10 +445,22 @@ export class EntityViewerComponent {
|
|
|
443
445
|
filterInput$ = new Subject();
|
|
444
446
|
/** Track if this is the first load (vs. load more) */
|
|
445
447
|
isInitialLoad = true;
|
|
448
|
+
/** Reference to the data grid component for flushing pending changes */
|
|
449
|
+
dataGridRef;
|
|
446
450
|
constructor(cdr) {
|
|
447
451
|
this.cdr = cdr;
|
|
448
452
|
}
|
|
449
453
|
// ========================================
|
|
454
|
+
// PUBLIC METHODS
|
|
455
|
+
// ========================================
|
|
456
|
+
/**
|
|
457
|
+
* Ensures any pending grid state changes are saved immediately without waiting for debounce.
|
|
458
|
+
* Call this before switching views or entities to ensure changes are saved.
|
|
459
|
+
*/
|
|
460
|
+
EnsurePendingChangesSaved() {
|
|
461
|
+
this.dataGridRef?.EnsurePendingChangesSaved();
|
|
462
|
+
}
|
|
463
|
+
// ========================================
|
|
450
464
|
// COMPUTED PROPERTIES
|
|
451
465
|
// ========================================
|
|
452
466
|
/**
|
|
@@ -488,12 +502,61 @@ export class EntityViewerComponent {
|
|
|
488
502
|
get effectiveSortState() {
|
|
489
503
|
return this.sortState ?? this.internalSortState;
|
|
490
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* Get the OrderBy string for mj-entity-data-grid from the effective sort state
|
|
507
|
+
*/
|
|
508
|
+
get effectiveSortOrderBy() {
|
|
509
|
+
const sortState = this.effectiveSortState;
|
|
510
|
+
if (!sortState?.field || !sortState.direction) {
|
|
511
|
+
return '';
|
|
512
|
+
}
|
|
513
|
+
return `${sortState.field} ${sortState.direction.toUpperCase()}`;
|
|
514
|
+
}
|
|
491
515
|
/**
|
|
492
516
|
* Get merged configuration with defaults
|
|
493
517
|
*/
|
|
494
518
|
get effectiveConfig() {
|
|
495
519
|
return { ...DEFAULT_VIEWER_CONFIG, ...this.config };
|
|
496
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* Get cached grid params - only recreates object when entity or viewEntity changes
|
|
523
|
+
* This prevents Angular from seeing a new object reference on every change detection
|
|
524
|
+
* which would cause the grid to reinitialize
|
|
525
|
+
*/
|
|
526
|
+
get gridParams() {
|
|
527
|
+
if (!this.entity) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
// Check if we need to recreate the params object
|
|
531
|
+
const entityChanged = this._lastGridParamsEntity !== this.entity.Name;
|
|
532
|
+
const viewEntityChanged = this._lastGridParamsViewEntity !== this.viewEntity;
|
|
533
|
+
if (entityChanged || viewEntityChanged || !this._cachedGridParams) {
|
|
534
|
+
this._lastGridParamsEntity = this.entity.Name;
|
|
535
|
+
this._lastGridParamsViewEntity = this.viewEntity ?? null;
|
|
536
|
+
this._cachedGridParams = {
|
|
537
|
+
EntityName: this.entity.Name,
|
|
538
|
+
ViewEntity: this.viewEntity || undefined
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
return this._cachedGridParams;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Get the effective grid toolbar configuration
|
|
545
|
+
* Merges user-provided config with defaults appropriate for entity-viewer context
|
|
546
|
+
*/
|
|
547
|
+
get effectiveGridToolbarConfig() {
|
|
548
|
+
const defaults = {
|
|
549
|
+
showSearch: false, // Entity-viewer has its own filter
|
|
550
|
+
showRefresh: true,
|
|
551
|
+
showAdd: true,
|
|
552
|
+
showDelete: true,
|
|
553
|
+
showExport: true,
|
|
554
|
+
showColumnChooser: true,
|
|
555
|
+
showRowCount: true,
|
|
556
|
+
showSelectionCount: true
|
|
557
|
+
};
|
|
558
|
+
return { ...defaults, ...this.gridToolbarConfig };
|
|
559
|
+
}
|
|
497
560
|
/**
|
|
498
561
|
* Get the records to display (external or internal)
|
|
499
562
|
*/
|
|
@@ -987,6 +1050,102 @@ export class EntityViewerComponent {
|
|
|
987
1050
|
this.loadMore();
|
|
988
1051
|
}
|
|
989
1052
|
// ========================================
|
|
1053
|
+
// DATA GRID EVENT HANDLERS
|
|
1054
|
+
// ========================================
|
|
1055
|
+
/**
|
|
1056
|
+
* Handle row click from mj-entity-data-grid
|
|
1057
|
+
* Maps to recordSelected event for parent components
|
|
1058
|
+
*/
|
|
1059
|
+
onDataGridRowClick(event) {
|
|
1060
|
+
if (!this.entity || !event.row)
|
|
1061
|
+
return;
|
|
1062
|
+
this.recordSelected.emit({
|
|
1063
|
+
record: event.row,
|
|
1064
|
+
entity: this.entity,
|
|
1065
|
+
compositeKey: event.row.PrimaryKey
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Handle row double-click from mj-entity-data-grid
|
|
1070
|
+
* Maps to recordOpened event for parent components
|
|
1071
|
+
*/
|
|
1072
|
+
onDataGridRowDoubleClick(event) {
|
|
1073
|
+
if (!this.entity || !event.row)
|
|
1074
|
+
return;
|
|
1075
|
+
this.recordOpened.emit({
|
|
1076
|
+
record: event.row,
|
|
1077
|
+
entity: this.entity,
|
|
1078
|
+
compositeKey: event.row.PrimaryKey
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Handle sort changed from mj-entity-data-grid
|
|
1083
|
+
* Maps to sortChanged event for parent components
|
|
1084
|
+
*/
|
|
1085
|
+
onDataGridSortChanged(event) {
|
|
1086
|
+
// Convert the data grid's sort state to our SortState format
|
|
1087
|
+
const newSort = event.newSortState && event.newSortState.length > 0
|
|
1088
|
+
? {
|
|
1089
|
+
field: event.newSortState[0].field,
|
|
1090
|
+
direction: event.newSortState[0].direction
|
|
1091
|
+
}
|
|
1092
|
+
: null;
|
|
1093
|
+
this.internalSortState = newSort;
|
|
1094
|
+
this.sortChanged.emit({ sort: newSort });
|
|
1095
|
+
// If server-side sorting, reload from page 1
|
|
1096
|
+
if (this.effectiveConfig.serverSideSorting && !this.records) {
|
|
1097
|
+
this.resetPaginationState();
|
|
1098
|
+
this.loadData();
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Handle Add/New button click from data grid toolbar
|
|
1103
|
+
*/
|
|
1104
|
+
onGridAddRequested() {
|
|
1105
|
+
this.addRequested.emit();
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Handle Refresh button click from data grid toolbar
|
|
1109
|
+
*/
|
|
1110
|
+
onGridRefreshRequested() {
|
|
1111
|
+
this.refreshRequested.emit();
|
|
1112
|
+
// Also trigger an internal refresh
|
|
1113
|
+
this.refresh();
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Handle Delete button click from data grid toolbar
|
|
1117
|
+
*/
|
|
1118
|
+
onGridDeleteRequested(records) {
|
|
1119
|
+
this.deleteRequested.emit({ records });
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Handle Export button click from data grid toolbar
|
|
1123
|
+
*/
|
|
1124
|
+
onGridExportRequested() {
|
|
1125
|
+
this.exportRequested.emit({ format: 'excel' });
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Handle Add to List button click from data grid toolbar.
|
|
1129
|
+
* Forwards the event to parent components for list management.
|
|
1130
|
+
*/
|
|
1131
|
+
onGridAddToListRequested(event) {
|
|
1132
|
+
this.addToListRequested.emit(event);
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Handle selection change from data grid.
|
|
1136
|
+
* Converts selected keys to records and forwards to parent components.
|
|
1137
|
+
*/
|
|
1138
|
+
onGridSelectionChange(selectedKeys) {
|
|
1139
|
+
// Find the actual records from our filtered records
|
|
1140
|
+
const records = this.filteredRecords.filter(record => {
|
|
1141
|
+
const key = record.PrimaryKey?.ToConcatenatedString() || String(record.Get('ID'));
|
|
1142
|
+
return selectedKeys.includes(key);
|
|
1143
|
+
});
|
|
1144
|
+
// Get the raw primary key values for list management
|
|
1145
|
+
const recordIds = records.map(record => String(record.PrimaryKey.KeyValuePairs[0].Value));
|
|
1146
|
+
this.selectionChanged.emit({ records, recordIds });
|
|
1147
|
+
}
|
|
1148
|
+
// ========================================
|
|
990
1149
|
// TIMELINE METHODS
|
|
991
1150
|
// ========================================
|
|
992
1151
|
/**
|
|
@@ -1230,30 +1389,75 @@ export class EntityViewerComponent {
|
|
|
1230
1389
|
const firstOther = fields.find(f => f.Name !== excludeField);
|
|
1231
1390
|
return firstOther?.Name || null;
|
|
1232
1391
|
}
|
|
1233
|
-
static ɵfac = function EntityViewerComponent_Factory(
|
|
1234
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityViewerComponent, selectors: [["mj-entity-viewer"]],
|
|
1392
|
+
static ɵfac = function EntityViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EntityViewerComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
1393
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityViewerComponent, selectors: [["mj-entity-viewer"]], viewQuery: function EntityViewerComponent_Query(rf, ctx) { if (rf & 1) {
|
|
1394
|
+
i0.ɵɵviewQuery(EntityDataGridComponent, 5);
|
|
1395
|
+
} if (rf & 2) {
|
|
1396
|
+
let _t;
|
|
1397
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dataGridRef = _t.first);
|
|
1398
|
+
} }, hostAttrs: [2, "display", "block", "height", "100%"], inputs: { entity: "entity", records: "records", config: "config", selectedRecordId: "selectedRecordId", viewMode: "viewMode", filterText: "filterText", sortState: "sortState", gridColumns: "gridColumns", cardTemplate: "cardTemplate", viewEntity: "viewEntity", gridState: "gridState", timelineConfig: "timelineConfig", showGridToolbar: "showGridToolbar", gridToolbarConfig: "gridToolbarConfig", gridSelectionMode: "gridSelectionMode", showAddToListButton: "showAddToListButton" }, outputs: { recordSelected: "recordSelected", recordOpened: "recordOpened", dataLoaded: "dataLoaded", viewModeChange: "viewModeChange", filterTextChange: "filterTextChange", filteredCountChanged: "filteredCountChanged", sortChanged: "sortChanged", gridStateChanged: "gridStateChanged", timelineConfigChange: "timelineConfigChange", addRequested: "addRequested", deleteRequested: "deleteRequested", refreshRequested: "refreshRequested", exportRequested: "exportRequested", addToListRequested: "addToListRequested", selectionChanged: "selectionChanged" }, features: [i0.ɵɵNgOnChangesFeature], decls: 19, vars: 38, consts: [[1, "entity-viewer-container"], [1, "viewer-header"], [1, "viewer-content"], [1, "loading-container", 3, "hidden"], ["size", "medium", 3, "text"], [1, "loading-overlay", 3, "hidden"], ["size", "small", 3, "text"], [1, "empty-state", 3, "hidden"], [1, "fa-solid", "fa-database"], [1, "fa-solid", "fa-inbox"], [3, "AfterRowClick", "AfterRowDoubleClick", "AfterSort", "GridStateChanged", "SelectionChange", "NewButtonClick", "RefreshButtonClick", "DeleteButtonClick", "ExportButtonClick", "AddToListRequested", "hidden", "Data", "Params", "FilterText", "GridState", "Height", "ShowToolbar", "ToolbarConfig", "SelectionMode", "ShowAddToListButton", "AllowLoad"], [3, "recordSelected", "recordOpened", "hidden", "entity", "records", "selectedRecordId", "cardTemplate", "hiddenFieldMatches", "filterText"], [3, "afterEventClick", "hidden", "groups", "orientation", "layout", "sortOrder", "segmentGrouping", "segmentsCollapsible", "segmentsDefaultExpanded", "selectedEventId"], [3, "pagination", "loadedRecordCount"], [1, "filter-container"], [1, "record-count"], [1, "view-mode-toggle"], [1, "fa-solid", "fa-search", "filter-icon"], ["type", "text", 1, "filter-input", 3, "input", "placeholder", "value"], ["title", "Clear filter", 1, "clear-filter-btn"], ["title", "Clear filter", 1, "clear-filter-btn", 3, "click"], [1, "fa-solid", "fa-times"], ["title", "Grid View", 1, "toggle-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Cards View", 1, "toggle-btn", 3, "click"], [1, "fa-solid", "fa-grip"], ["title", "Timeline View", 1, "toggle-btn", 3, "active"], ["title", "Timeline View", 1, "toggle-btn", 3, "click"], [1, "fa-solid", "fa-timeline"], [1, "timeline-date-selector"], [1, "fa-solid", "fa-calendar-days"], [1, "date-field-label"], [1, "date-field-select", 3, "value"], [1, "timeline-orientation-toggle"], [1, "toggle-btn", 3, "click", "title"], [1, "timeline-sort-toggle"], [1, "date-field-select", 3, "change", "value"], [3, "value"], [3, "loadMore", "pagination", "loadedRecordCount"]], template: function EntityViewerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1235
1399
|
i0.ɵɵelementStart(0, "div", 0);
|
|
1236
1400
|
i0.ɵɵtemplate(1, EntityViewerComponent_Conditional_1_Template, 5, 4, "div", 1);
|
|
1237
|
-
i0.ɵɵelementStart(2, "div", 2);
|
|
1238
|
-
i0.ɵɵ
|
|
1401
|
+
i0.ɵɵelementStart(2, "div", 2)(3, "div", 3);
|
|
1402
|
+
i0.ɵɵelement(4, "mj-loading", 4);
|
|
1403
|
+
i0.ɵɵelementEnd();
|
|
1404
|
+
i0.ɵɵelementStart(5, "div", 5);
|
|
1405
|
+
i0.ɵɵelement(6, "mj-loading", 6);
|
|
1239
1406
|
i0.ɵɵelementEnd();
|
|
1240
|
-
i0.ɵɵ
|
|
1407
|
+
i0.ɵɵelementStart(7, "div", 7);
|
|
1408
|
+
i0.ɵɵelement(8, "i", 8);
|
|
1409
|
+
i0.ɵɵelementStart(9, "p");
|
|
1410
|
+
i0.ɵɵtext(10, "Select an entity to view records");
|
|
1411
|
+
i0.ɵɵelementEnd()();
|
|
1412
|
+
i0.ɵɵelementStart(11, "div", 7);
|
|
1413
|
+
i0.ɵɵelement(12, "i", 9);
|
|
1414
|
+
i0.ɵɵelementStart(13, "p");
|
|
1415
|
+
i0.ɵɵtext(14);
|
|
1416
|
+
i0.ɵɵelementEnd()();
|
|
1417
|
+
i0.ɵɵelementStart(15, "mj-entity-data-grid", 10);
|
|
1418
|
+
i0.ɵɵlistener("AfterRowClick", function EntityViewerComponent_Template_mj_entity_data_grid_AfterRowClick_15_listener($event) { return ctx.onDataGridRowClick($event); })("AfterRowDoubleClick", function EntityViewerComponent_Template_mj_entity_data_grid_AfterRowDoubleClick_15_listener($event) { return ctx.onDataGridRowDoubleClick($event); })("AfterSort", function EntityViewerComponent_Template_mj_entity_data_grid_AfterSort_15_listener($event) { return ctx.onDataGridSortChanged($event); })("GridStateChanged", function EntityViewerComponent_Template_mj_entity_data_grid_GridStateChanged_15_listener($event) { return ctx.onGridStateChanged($event); })("SelectionChange", function EntityViewerComponent_Template_mj_entity_data_grid_SelectionChange_15_listener($event) { return ctx.onGridSelectionChange($event); })("NewButtonClick", function EntityViewerComponent_Template_mj_entity_data_grid_NewButtonClick_15_listener() { return ctx.onGridAddRequested(); })("RefreshButtonClick", function EntityViewerComponent_Template_mj_entity_data_grid_RefreshButtonClick_15_listener() { return ctx.onGridRefreshRequested(); })("DeleteButtonClick", function EntityViewerComponent_Template_mj_entity_data_grid_DeleteButtonClick_15_listener($event) { return ctx.onGridDeleteRequested($event); })("ExportButtonClick", function EntityViewerComponent_Template_mj_entity_data_grid_ExportButtonClick_15_listener() { return ctx.onGridExportRequested(); })("AddToListRequested", function EntityViewerComponent_Template_mj_entity_data_grid_AddToListRequested_15_listener($event) { return ctx.onGridAddToListRequested($event); });
|
|
1419
|
+
i0.ɵɵelementEnd();
|
|
1420
|
+
i0.ɵɵelementStart(16, "mj-entity-cards", 11);
|
|
1421
|
+
i0.ɵɵlistener("recordSelected", function EntityViewerComponent_Template_mj_entity_cards_recordSelected_16_listener($event) { return ctx.onRecordSelected($event); })("recordOpened", function EntityViewerComponent_Template_mj_entity_cards_recordOpened_16_listener($event) { return ctx.onRecordOpened($event); });
|
|
1422
|
+
i0.ɵɵelementEnd();
|
|
1423
|
+
i0.ɵɵelementStart(17, "mj-timeline", 12);
|
|
1424
|
+
i0.ɵɵlistener("afterEventClick", function EntityViewerComponent_Template_mj_timeline_afterEventClick_17_listener($event) { return ctx.onTimelineEventClick($event); });
|
|
1425
|
+
i0.ɵɵelementEnd()();
|
|
1426
|
+
i0.ɵɵtemplate(18, EntityViewerComponent_Conditional_18_Template, 1, 2, "mj-pagination", 13);
|
|
1241
1427
|
i0.ɵɵelementEnd();
|
|
1242
1428
|
} if (rf & 2) {
|
|
1243
1429
|
i0.ɵɵstyleProp("height", ctx.effectiveConfig.height);
|
|
1244
1430
|
i0.ɵɵadvance();
|
|
1245
1431
|
i0.ɵɵconditional(ctx.effectiveConfig.showFilter || ctx.effectiveConfig.showViewModeToggle || ctx.effectiveConfig.showRecordCount ? 1 : -1);
|
|
1246
1432
|
i0.ɵɵadvance(2);
|
|
1247
|
-
i0.ɵɵ
|
|
1433
|
+
i0.ɵɵproperty("hidden", !(ctx.isLoading && ctx.filteredRecords.length === 0));
|
|
1434
|
+
i0.ɵɵadvance();
|
|
1435
|
+
i0.ɵɵproperty("text", ctx.loadingMessage);
|
|
1436
|
+
i0.ɵɵadvance();
|
|
1437
|
+
i0.ɵɵproperty("hidden", !(ctx.isLoading && ctx.filteredRecords.length > 0));
|
|
1438
|
+
i0.ɵɵadvance();
|
|
1439
|
+
i0.ɵɵproperty("text", ctx.loadingMessage);
|
|
1440
|
+
i0.ɵɵadvance();
|
|
1441
|
+
i0.ɵɵproperty("hidden", !!ctx.entity);
|
|
1248
1442
|
i0.ɵɵadvance(4);
|
|
1249
|
-
i0.ɵɵ
|
|
1250
|
-
|
|
1443
|
+
i0.ɵɵproperty("hidden", !ctx.entity || ctx.filteredRecords.length > 0 || ctx.isLoading);
|
|
1444
|
+
i0.ɵɵadvance(3);
|
|
1445
|
+
i0.ɵɵtextInterpolate(ctx.debouncedFilterText ? "No matching records" : "No records found");
|
|
1446
|
+
i0.ɵɵadvance();
|
|
1447
|
+
i0.ɵɵproperty("hidden", ctx.effectiveViewMode !== "grid" || !ctx.entity)("Data", ctx.filteredRecords)("Params", ctx.gridParams)("FilterText", ctx.debouncedFilterText)("GridState", ctx.gridState)("Height", "auto")("ShowToolbar", ctx.showGridToolbar)("ToolbarConfig", ctx.effectiveGridToolbarConfig)("SelectionMode", ctx.gridSelectionMode)("ShowAddToListButton", ctx.showAddToListButton)("AllowLoad", false);
|
|
1448
|
+
i0.ɵɵadvance();
|
|
1449
|
+
i0.ɵɵproperty("hidden", ctx.effectiveViewMode !== "cards" || !ctx.entity)("entity", ctx.entity)("records", ctx.filteredRecords)("selectedRecordId", ctx.selectedRecordId)("cardTemplate", ctx.cardTemplate)("hiddenFieldMatches", ctx.hiddenFieldMatches)("filterText", ctx.debouncedFilterText);
|
|
1450
|
+
i0.ɵɵadvance();
|
|
1451
|
+
i0.ɵɵproperty("hidden", ctx.effectiveViewMode !== "timeline" || !ctx.hasDateFields)("groups", ctx.timelineGroups)("orientation", ctx.timelineOrientation)("layout", ctx.timelineOrientation === "vertical" ? "alternating" : "single")("sortOrder", ctx.timelineSortOrder)("segmentGrouping", ctx.timelineSegmentGrouping)("segmentsCollapsible", true)("segmentsDefaultExpanded", true)("selectedEventId", ctx.timelineSelectedEventId);
|
|
1452
|
+
i0.ɵɵadvance();
|
|
1453
|
+
i0.ɵɵconditional(ctx.effectiveConfig.showPagination && ctx.entity && (ctx.pagination.hasMore || ctx.pagination.totalRecords > ctx.effectiveConfig.pageSize) ? 18 : -1);
|
|
1454
|
+
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i2.LoadingComponent, i3.TimelineComponent, i4.EntityCardsComponent, i5.PaginationComponent, i6.EntityDataGridComponent, i7.DecimalPipe], styles: [".entity-viewer-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n background: #fafafa;\n}\n\n\n\nmj-pagination[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n\n\n.viewer-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 12px 16px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n\n\n.filter-container[_ngcontent-%COMP%] {\n flex: 1;\n max-width: 400px;\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.filter-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n color: #9e9e9e;\n font-size: 14px;\n pointer-events: none;\n}\n\n.filter-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 36px 8px 36px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.filter-input[_ngcontent-%COMP%]:focus {\n border-color: #1976d2;\n}\n\n.filter-input[_ngcontent-%COMP%]::placeholder {\n color: #9e9e9e;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n width: 20px;\n height: 20px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #9e9e9e;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n color: #616161;\n}\n\n\n\n.record-count[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #757575;\n white-space: nowrap;\n}\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f5f5f5;\n border-radius: 6px;\n padding: 2px;\n}\n\n.toggle-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n\n.toggle-btn[_ngcontent-%COMP%]:hover {\n color: #424242;\n}\n\n.toggle-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n.timeline-date-selector[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: #616161;\n}\n\n.timeline-date-selector[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #9e9e9e;\n}\n\n.date-field-label[_ngcontent-%COMP%] {\n color: #424242;\n font-weight: 500;\n}\n\n.date-field-select[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 13px;\n background: white;\n color: #424242;\n cursor: pointer;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.date-field-select[_ngcontent-%COMP%]:hover {\n border-color: #bdbdbd;\n}\n\n.date-field-select[_ngcontent-%COMP%]:focus {\n border-color: #1976d2;\n}\n\n\n\n.timeline-orientation-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f5f5f5;\n border-radius: 6px;\n padding: 2px;\n}\n\n\n\n.viewer-content[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n position: relative;\n background: white;\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n\n\n.loading-overlay[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.8);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #9e9e9e;\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\nmj-entity-cards[hidden][_ngcontent-%COMP%], \nmj-timeline[hidden][_ngcontent-%COMP%] {\n display: none !important;\n}\n\n\n\nmj-entity-cards[_ngcontent-%COMP%]:not([hidden]), \nmj-timeline[_ngcontent-%COMP%]:not([hidden]) {\n display: block;\n height: 100%;\n width: 100%;\n}"] });
|
|
1251
1455
|
}
|
|
1252
1456
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityViewerComponent, [{
|
|
1253
1457
|
type: Component,
|
|
1254
1458
|
args: [{ selector: 'mj-entity-viewer', host: {
|
|
1255
1459
|
'style': 'display: block; height: 100%;'
|
|
1256
|
-
}, template: "<div class=\"entity-viewer-container\" [style.height]=\"effectiveConfig.height\">\n <!-- Header -->\n @if (effectiveConfig.showFilter || effectiveConfig.showViewModeToggle || effectiveConfig.showRecordCount) {\n <div class=\"viewer-header\">\n <!-- Filter Input -->\n @if (effectiveConfig.showFilter) {\n <div class=\"filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n type=\"text\"\n class=\"filter-input\"\n [placeholder]=\"effectiveConfig.filterPlaceholder\"\n [value]=\"effectiveFilterText\"\n (input)=\"onFilterChange($any($event.target).value)\"\n />\n @if (effectiveFilterText) {\n <button class=\"clear-filter-btn\" (click)=\"clearFilter()\" title=\"Clear filter\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Record Count -->\n @if (effectiveConfig.showRecordCount && entity) {\n <div class=\"record-count\">\n @if (filteredRecordCount !== totalRecordCount) {\n <span>{{ filteredRecordCount | number }} of {{ totalRecordCount | number }} records</span>\n } @else {\n <span>{{ totalRecordCount | number }} records</span>\n }\n </div>\n }\n\n <!-- View Mode Toggle -->\n @if (effectiveConfig.showViewModeToggle) {\n <div class=\"view-mode-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"effectiveViewMode === 'grid'\"\n (click)=\"setViewMode('grid')\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"effectiveViewMode === 'cards'\"\n (click)=\"setViewMode('cards')\"\n title=\"Cards View\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n @if (hasDateFields) {\n <button\n class=\"toggle-btn\"\n [class.active]=\"effectiveViewMode === 'timeline'\"\n (click)=\"setViewMode('timeline')\"\n title=\"Timeline View\">\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Timeline Controls (only shown when timeline is active) -->\n @if (effectiveViewMode === 'timeline' && hasDateFields) {\n <!-- Date Field Selector -->\n <div class=\"timeline-date-selector\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n @if (availableDateFields.length === 1) {\n <span class=\"date-field-label\">{{ selectedDateFieldDisplayName }}</span>\n } @else {\n <select\n class=\"date-field-select\"\n [value]=\"selectedTimelineDateField\"\n (change)=\"setTimelineDateField($any($event.target).value)\">\n @for (field of availableDateFields; track field.Name) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n }\n </div>\n\n <!-- Orientation Toggle -->\n <div class=\"timeline-orientation-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"toggleTimelineOrientation()\"\n [title]=\"timelineOrientation === 'vertical' ? 'Switch to Horizontal' : 'Switch to Vertical'\">\n <i [class]=\"timelineOrientation === 'vertical' ? 'fa-solid fa-ellipsis-vertical' : 'fa-solid fa-ellipsis'\"></i>\n </button>\n </div>\n\n <!-- Sort Order Toggle -->\n <div class=\"timeline-sort-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"toggleTimelineSortOrder()\"\n [title]=\"timelineSortOrder === 'desc' ? 'Showing Newest First (click for Oldest First)' : 'Showing Oldest First (click for Newest First)'\">\n <i [class]=\"timelineSortOrder === 'desc' ? 'fa-solid fa-arrow-down-wide-short' : 'fa-solid fa-arrow-up-wide-short'\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Content -->\n <div class=\"viewer-content\">\n @if (isLoading && filteredRecords.length === 0) {\n <!-- Initial loading state -->\n <div class=\"loading-container\">\n <mj-loading [text]=\"loadingMessage\" size=\"medium\"></mj-loading>\n </div>\n } @else if (!entity) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-database\"></i>\n <p>Select an entity to view records</p>\n </div>\n } @else if (filteredRecords.length === 0 && !isLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>{{ debouncedFilterText ? 'No matching records' : 'No records found' }}</p>\n </div>\n } @else {\n <!-- Grid View - always rendered but hidden when not active to preserve state -->\n <mj-entity-grid\n [hidden]=\"effectiveViewMode !== 'grid'\"\n [entity]=\"entity\"\n [records]=\"filteredRecords\"\n [selectedRecordId]=\"selectedRecordId\"\n [columns]=\"gridColumns\"\n [height]=\"'100%'\"\n [filterText]=\"debouncedFilterText\"\n [sortState]=\"effectiveSortState\"\n [serverSideSorting]=\"effectiveConfig.serverSideSorting\"\n [gridState]=\"gridState\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\"\n (sortChanged)=\"onSortChanged($event)\"\n (gridStateChanged)=\"onGridStateChanged($event)\">\n </mj-entity-grid>\n\n <!-- Cards View - always rendered but hidden when not active to preserve state -->\n <mj-entity-cards\n [hidden]=\"effectiveViewMode !== 'cards'\"\n [entity]=\"entity\"\n [records]=\"filteredRecords\"\n [selectedRecordId]=\"selectedRecordId\"\n [cardTemplate]=\"cardTemplate\"\n [hiddenFieldMatches]=\"hiddenFieldMatches\"\n [filterText]=\"debouncedFilterText\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\">\n </mj-entity-cards>\n\n <!-- Timeline View - only created when timeline mode is active -->\n @if (hasDateFields && effectiveViewMode === 'timeline') {\n <mj-timeline\n [groups]=\"timelineGroups\"\n [orientation]=\"timelineOrientation\"\n [layout]=\"timelineOrientation === 'vertical' ? 'alternating' : 'single'\"\n [sortOrder]=\"timelineSortOrder\"\n [segmentGrouping]=\"timelineSegmentGrouping\"\n [segmentsCollapsible]=\"true\"\n [segmentsDefaultExpanded]=\"true\"\n [selectedEventId]=\"timelineSelectedEventId\"\n (afterEventClick)=\"onTimelineEventClick($event)\">\n </mj-timeline>\n }\n }\n </div>\n\n <!-- Pagination - only show when there's more data to load OR we've loaded more than one page -->\n @if (effectiveConfig.showPagination && entity && (pagination.hasMore || pagination.totalRecords > effectiveConfig.pageSize)) {\n <mj-pagination\n [pagination]=\"pagination\"\n [loadedRecordCount]=\"filteredRecords.length\"\n (loadMore)=\"onLoadMore()\">\n </mj-pagination>\n }\n</div>\n", styles: [".entity-viewer-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n background: #fafafa;\n}\n\n/* Header */\n.viewer-header {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 12px 16px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n/* Filter */\n.filter-container {\n flex: 1;\n max-width: 400px;\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.filter-icon {\n position: absolute;\n left: 12px;\n color: #9e9e9e;\n font-size: 14px;\n pointer-events: none;\n}\n\n.filter-input {\n width: 100%;\n padding: 8px 36px 8px 36px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.filter-input:focus {\n border-color: #1976d2;\n}\n\n.filter-input::placeholder {\n color: #9e9e9e;\n}\n\n.clear-filter-btn {\n position: absolute;\n right: 8px;\n width: 20px;\n height: 20px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #9e9e9e;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn:hover {\n background: #f5f5f5;\n color: #616161;\n}\n\n/* Record Count */\n.record-count {\n font-size: 13px;\n color: #757575;\n white-space: nowrap;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n background: #f5f5f5;\n border-radius: 6px;\n padding: 2px;\n}\n\n.toggle-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n\n.toggle-btn:hover {\n color: #424242;\n}\n\n.toggle-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Timeline Date Field Selector */\n.timeline-date-selector {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: #616161;\n}\n\n.timeline-date-selector i {\n color: #9e9e9e;\n}\n\n.date-field-label {\n color: #424242;\n font-weight: 500;\n}\n\n.date-field-select {\n padding: 4px 8px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 13px;\n background: white;\n color: #424242;\n cursor: pointer;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.date-field-select:hover {\n border-color: #bdbdbd;\n}\n\n.date-field-select:focus {\n border-color: #1976d2;\n}\n\n/* Timeline Orientation Toggle */\n.timeline-orientation-toggle {\n display: flex;\n background: #f5f5f5;\n border-radius: 6px;\n padding: 2px;\n}\n\n/* Content */\n.viewer-content {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n position: relative;\n background: white;\n}\n\n/* Loading State */\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #9e9e9e;\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* Hidden components should not display - ensure [hidden] attribute works properly */\nmj-entity-grid[hidden],\nmj-entity-cards[hidden],\nmj-timeline[hidden] {\n display: none !important;\n}\n\n/* Visible view components should fill available space */\nmj-entity-grid:not([hidden]),\nmj-entity-cards:not([hidden]),\nmj-timeline:not([hidden]) {\n display: block;\n height: 100%;\n width: 100%;\n}\n"] }]
|
|
1460
|
+
}, template: "<div class=\"entity-viewer-container\" [style.height]=\"effectiveConfig.height\">\n <!-- Header -->\n @if (effectiveConfig.showFilter || effectiveConfig.showViewModeToggle || effectiveConfig.showRecordCount) {\n <div class=\"viewer-header\">\n <!-- Filter Input -->\n @if (effectiveConfig.showFilter) {\n <div class=\"filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n type=\"text\"\n class=\"filter-input\"\n [placeholder]=\"effectiveConfig.filterPlaceholder\"\n [value]=\"effectiveFilterText\"\n (input)=\"onFilterChange($any($event.target).value)\"\n />\n @if (effectiveFilterText) {\n <button class=\"clear-filter-btn\" (click)=\"clearFilter()\" title=\"Clear filter\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Record Count -->\n @if (effectiveConfig.showRecordCount && entity) {\n <div class=\"record-count\">\n @if (filteredRecordCount !== totalRecordCount) {\n <span>{{ filteredRecordCount | number }} of {{ totalRecordCount | number }} records</span>\n } @else {\n <span>{{ totalRecordCount | number }} records</span>\n }\n </div>\n }\n\n <!-- View Mode Toggle -->\n @if (effectiveConfig.showViewModeToggle) {\n <div class=\"view-mode-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"effectiveViewMode === 'grid'\"\n (click)=\"setViewMode('grid')\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"effectiveViewMode === 'cards'\"\n (click)=\"setViewMode('cards')\"\n title=\"Cards View\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n @if (hasDateFields) {\n <button\n class=\"toggle-btn\"\n [class.active]=\"effectiveViewMode === 'timeline'\"\n (click)=\"setViewMode('timeline')\"\n title=\"Timeline View\">\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Timeline Controls (only shown when timeline is active) -->\n @if (effectiveViewMode === 'timeline' && hasDateFields) {\n <!-- Date Field Selector -->\n <div class=\"timeline-date-selector\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n @if (availableDateFields.length === 1) {\n <span class=\"date-field-label\">{{ selectedDateFieldDisplayName }}</span>\n } @else {\n <select\n class=\"date-field-select\"\n [value]=\"selectedTimelineDateField\"\n (change)=\"setTimelineDateField($any($event.target).value)\">\n @for (field of availableDateFields; track field.Name) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n }\n </div>\n\n <!-- Orientation Toggle -->\n <div class=\"timeline-orientation-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"toggleTimelineOrientation()\"\n [title]=\"timelineOrientation === 'vertical' ? 'Switch to Horizontal' : 'Switch to Vertical'\">\n <i [class]=\"timelineOrientation === 'vertical' ? 'fa-solid fa-ellipsis-vertical' : 'fa-solid fa-ellipsis'\"></i>\n </button>\n </div>\n\n <!-- Sort Order Toggle -->\n <div class=\"timeline-sort-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"toggleTimelineSortOrder()\"\n [title]=\"timelineSortOrder === 'desc' ? 'Showing Newest First (click for Oldest First)' : 'Showing Oldest First (click for Newest First)'\">\n <i [class]=\"timelineSortOrder === 'desc' ? 'fa-solid fa-arrow-down-wide-short' : 'fa-solid fa-arrow-up-wide-short'\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <!-- Content -->\n <div class=\"viewer-content\">\n <!-- Loading container - full page when no data exists -->\n <div class=\"loading-container\" [hidden]=\"!(isLoading && filteredRecords.length === 0)\">\n <mj-loading [text]=\"loadingMessage\" size=\"medium\"></mj-loading>\n </div>\n\n <!-- Loading overlay - shown on top of content when loading with existing data -->\n <div class=\"loading-overlay\" [hidden]=\"!(isLoading && filteredRecords.length > 0)\">\n <mj-loading [text]=\"loadingMessage\" size=\"small\"></mj-loading>\n </div>\n\n <!-- Empty state: no entity selected -->\n <div class=\"empty-state\" [hidden]=\"!!entity\">\n <i class=\"fa-solid fa-database\"></i>\n <p>Select an entity to view records</p>\n </div>\n\n <!-- Empty state: no records found -->\n <div class=\"empty-state\" [hidden]=\"!entity || filteredRecords.length > 0 || isLoading\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>{{ debouncedFilterText ? 'No matching records' : 'No records found' }}</p>\n </div>\n\n <!-- Grid View - always rendered, visibility controlled by hidden -->\n <mj-entity-data-grid\n [hidden]=\"effectiveViewMode !== 'grid' || !entity\"\n [Data]=\"filteredRecords\"\n [Params]=\"gridParams\"\n [FilterText]=\"debouncedFilterText\"\n [GridState]=\"gridState\"\n [Height]=\"'auto'\"\n [ShowToolbar]=\"showGridToolbar\"\n [ToolbarConfig]=\"effectiveGridToolbarConfig\"\n [SelectionMode]=\"gridSelectionMode\"\n [ShowAddToListButton]=\"showAddToListButton\"\n [AllowLoad]=\"false\"\n (AfterRowClick)=\"onDataGridRowClick($event)\"\n (AfterRowDoubleClick)=\"onDataGridRowDoubleClick($event)\"\n (AfterSort)=\"onDataGridSortChanged($event)\"\n (GridStateChanged)=\"onGridStateChanged($event)\"\n (SelectionChange)=\"onGridSelectionChange($event)\"\n (NewButtonClick)=\"onGridAddRequested()\"\n (RefreshButtonClick)=\"onGridRefreshRequested()\"\n (DeleteButtonClick)=\"onGridDeleteRequested($event)\"\n (ExportButtonClick)=\"onGridExportRequested()\"\n (AddToListRequested)=\"onGridAddToListRequested($event)\">\n </mj-entity-data-grid>\n\n <!-- Cards View - always rendered, visibility controlled by hidden -->\n <mj-entity-cards\n [hidden]=\"effectiveViewMode !== 'cards' || !entity\"\n [entity]=\"entity\"\n [records]=\"filteredRecords\"\n [selectedRecordId]=\"selectedRecordId\"\n [cardTemplate]=\"cardTemplate\"\n [hiddenFieldMatches]=\"hiddenFieldMatches\"\n [filterText]=\"debouncedFilterText\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\">\n </mj-entity-cards>\n\n <!-- Timeline View - always rendered when date fields exist, visibility controlled by hidden -->\n <mj-timeline\n [hidden]=\"effectiveViewMode !== 'timeline' || !hasDateFields\"\n [groups]=\"timelineGroups\"\n [orientation]=\"timelineOrientation\"\n [layout]=\"timelineOrientation === 'vertical' ? 'alternating' : 'single'\"\n [sortOrder]=\"timelineSortOrder\"\n [segmentGrouping]=\"timelineSegmentGrouping\"\n [segmentsCollapsible]=\"true\"\n [segmentsDefaultExpanded]=\"true\"\n [selectedEventId]=\"timelineSelectedEventId\"\n (afterEventClick)=\"onTimelineEventClick($event)\">\n </mj-timeline>\n </div>\n\n <!-- Pagination - only show when there's more data to load OR we've loaded more than one page -->\n @if (effectiveConfig.showPagination && entity && (pagination.hasMore || pagination.totalRecords > effectiveConfig.pageSize)) {\n <mj-pagination\n [pagination]=\"pagination\"\n [loadedRecordCount]=\"filteredRecords.length\"\n (loadMore)=\"onLoadMore()\">\n </mj-pagination>\n }\n</div>\n", styles: [".entity-viewer-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n background: #fafafa;\n}\n\n/* Pagination footer - always visible at bottom */\nmj-pagination {\n flex-shrink: 0;\n}\n\n/* Header */\n.viewer-header {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 12px 16px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n/* Filter */\n.filter-container {\n flex: 1;\n max-width: 400px;\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.filter-icon {\n position: absolute;\n left: 12px;\n color: #9e9e9e;\n font-size: 14px;\n pointer-events: none;\n}\n\n.filter-input {\n width: 100%;\n padding: 8px 36px 8px 36px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.filter-input:focus {\n border-color: #1976d2;\n}\n\n.filter-input::placeholder {\n color: #9e9e9e;\n}\n\n.clear-filter-btn {\n position: absolute;\n right: 8px;\n width: 20px;\n height: 20px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #9e9e9e;\n transition: all 0.15s ease;\n}\n\n.clear-filter-btn:hover {\n background: #f5f5f5;\n color: #616161;\n}\n\n/* Record Count */\n.record-count {\n font-size: 13px;\n color: #757575;\n white-space: nowrap;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n background: #f5f5f5;\n border-radius: 6px;\n padding: 2px;\n}\n\n.toggle-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n\n.toggle-btn:hover {\n color: #424242;\n}\n\n.toggle-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Timeline Date Field Selector */\n.timeline-date-selector {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: #616161;\n}\n\n.timeline-date-selector i {\n color: #9e9e9e;\n}\n\n.date-field-label {\n color: #424242;\n font-weight: 500;\n}\n\n.date-field-select {\n padding: 4px 8px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 13px;\n background: white;\n color: #424242;\n cursor: pointer;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.date-field-select:hover {\n border-color: #bdbdbd;\n}\n\n.date-field-select:focus {\n border-color: #1976d2;\n}\n\n/* Timeline Orientation Toggle */\n.timeline-orientation-toggle {\n display: flex;\n background: #f5f5f5;\n border-radius: 6px;\n padding: 2px;\n}\n\n/* Content */\n.viewer-content {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n position: relative;\n background: white;\n}\n\n/* Loading State - positioned as overlay when data exists */\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n/* Loading overlay when shown on top of content */\n.loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.8);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #9e9e9e;\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* Hidden components should not display - ensure [hidden] attribute works properly */\nmj-entity-cards[hidden],\nmj-timeline[hidden] {\n display: none !important;\n}\n\n/* Visible view components should fill available space */\nmj-entity-cards:not([hidden]),\nmj-timeline:not([hidden]) {\n display: block;\n height: 100%;\n width: 100%;\n}\n"] }]
|
|
1257
1461
|
}], () => [{ type: i0.ChangeDetectorRef }], { entity: [{
|
|
1258
1462
|
type: Input
|
|
1259
1463
|
}], records: [{
|
|
@@ -1278,6 +1482,14 @@ export class EntityViewerComponent {
|
|
|
1278
1482
|
type: Input
|
|
1279
1483
|
}], timelineConfig: [{
|
|
1280
1484
|
type: Input
|
|
1485
|
+
}], showGridToolbar: [{
|
|
1486
|
+
type: Input
|
|
1487
|
+
}], gridToolbarConfig: [{
|
|
1488
|
+
type: Input
|
|
1489
|
+
}], gridSelectionMode: [{
|
|
1490
|
+
type: Input
|
|
1491
|
+
}], showAddToListButton: [{
|
|
1492
|
+
type: Input
|
|
1281
1493
|
}], recordSelected: [{
|
|
1282
1494
|
type: Output
|
|
1283
1495
|
}], recordOpened: [{
|
|
@@ -1296,6 +1508,21 @@ export class EntityViewerComponent {
|
|
|
1296
1508
|
type: Output
|
|
1297
1509
|
}], timelineConfigChange: [{
|
|
1298
1510
|
type: Output
|
|
1511
|
+
}], addRequested: [{
|
|
1512
|
+
type: Output
|
|
1513
|
+
}], deleteRequested: [{
|
|
1514
|
+
type: Output
|
|
1515
|
+
}], refreshRequested: [{
|
|
1516
|
+
type: Output
|
|
1517
|
+
}], exportRequested: [{
|
|
1518
|
+
type: Output
|
|
1519
|
+
}], addToListRequested: [{
|
|
1520
|
+
type: Output
|
|
1521
|
+
}], selectionChanged: [{
|
|
1522
|
+
type: Output
|
|
1523
|
+
}], dataGridRef: [{
|
|
1524
|
+
type: ViewChild,
|
|
1525
|
+
args: [EntityDataGridComponent]
|
|
1299
1526
|
}] }); })();
|
|
1300
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityViewerComponent, { className: "EntityViewerComponent"
|
|
1527
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityViewerComponent, { className: "EntityViewerComponent" }); })();
|
|
1301
1528
|
//# sourceMappingURL=entity-viewer.component.js.map
|