@memberjunction/ng-versions 0.0.1 → 4.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/dist/lib/label-create/label-create.component.d.ts +71 -0
- package/dist/lib/label-create/label-create.component.d.ts.map +1 -0
- package/dist/lib/label-create/label-create.component.js +776 -0
- package/dist/lib/label-create/label-create.component.js.map +1 -0
- package/dist/lib/label-detail/label-detail.component.d.ts +186 -0
- package/dist/lib/label-detail/label-detail.component.d.ts.map +1 -0
- package/dist/lib/label-detail/label-detail.component.js +2076 -0
- package/dist/lib/label-detail/label-detail.component.js.map +1 -0
- package/dist/lib/panel/slide-panel.component.d.ts +35 -0
- package/dist/lib/panel/slide-panel.component.d.ts.map +1 -0
- package/dist/lib/panel/slide-panel.component.js +199 -0
- package/dist/lib/panel/slide-panel.component.js.map +1 -0
- package/dist/lib/record-micro-view/record-micro-view.component.d.ts +114 -0
- package/dist/lib/record-micro-view/record-micro-view.component.d.ts.map +1 -0
- package/dist/lib/record-micro-view/record-micro-view.component.js +824 -0
- package/dist/lib/record-micro-view/record-micro-view.component.js.map +1 -0
- package/dist/lib/types.d.ts +22 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +5 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/versions.module.d.ts +14 -0
- package/dist/lib/versions.module.d.ts.map +1 -0
- package/dist/lib/versions.module.js +48 -0
- package/dist/lib/versions.module.js.map +1 -0
- package/dist/public-api.d.ts +7 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +7 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +37 -7
- package/README.md +0 -45
|
@@ -0,0 +1,824 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, HostListener } from '@angular/core';
|
|
2
|
+
import { RunView, Metadata, CompositeKey } from '@memberjunction/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@angular/common";
|
|
5
|
+
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
6
|
+
function MjRecordMicroViewComponent_Conditional_0_ng_container_2_Template(rf, ctx) { if (rf & 1) {
|
|
7
|
+
i0.ɵɵelementContainer(0);
|
|
8
|
+
} }
|
|
9
|
+
function MjRecordMicroViewComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
11
|
+
i0.ɵɵelementStart(0, "div", 2);
|
|
12
|
+
i0.ɵɵlistener("click", function MjRecordMicroViewComponent_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnBackdropClick()); });
|
|
13
|
+
i0.ɵɵelementEnd();
|
|
14
|
+
i0.ɵɵelementStart(1, "div", 3);
|
|
15
|
+
i0.ɵɵtemplate(2, MjRecordMicroViewComponent_Conditional_0_ng_container_2_Template, 1, 0, "ng-container", 4);
|
|
16
|
+
i0.ɵɵelementEnd();
|
|
17
|
+
} if (rf & 2) {
|
|
18
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
19
|
+
const microContent_r3 = i0.ɵɵreference(3);
|
|
20
|
+
i0.ɵɵclassProp("visible", ctx_r1.IsVisible);
|
|
21
|
+
i0.ɵɵadvance();
|
|
22
|
+
i0.ɵɵclassProp("visible", ctx_r1.IsVisible);
|
|
23
|
+
i0.ɵɵadvance();
|
|
24
|
+
i0.ɵɵproperty("ngTemplateOutlet", microContent_r3);
|
|
25
|
+
} }
|
|
26
|
+
function MjRecordMicroViewComponent_Conditional_1_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
27
|
+
i0.ɵɵelementContainer(0);
|
|
28
|
+
} }
|
|
29
|
+
function MjRecordMicroViewComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
30
|
+
i0.ɵɵelementStart(0, "div", 1);
|
|
31
|
+
i0.ɵɵtemplate(1, MjRecordMicroViewComponent_Conditional_1_ng_container_1_Template, 1, 0, "ng-container", 4);
|
|
32
|
+
i0.ɵɵelementEnd();
|
|
33
|
+
} if (rf & 2) {
|
|
34
|
+
i0.ɵɵnextContext();
|
|
35
|
+
const microContent_r3 = i0.ɵɵreference(3);
|
|
36
|
+
i0.ɵɵadvance();
|
|
37
|
+
i0.ɵɵproperty("ngTemplateOutlet", microContent_r3);
|
|
38
|
+
} }
|
|
39
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_0_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
40
|
+
i0.ɵɵelementStart(0, "span", 15);
|
|
41
|
+
i0.ɵɵtext(1);
|
|
42
|
+
i0.ɵɵelementEnd();
|
|
43
|
+
} if (rf & 2) {
|
|
44
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
45
|
+
i0.ɵɵadvance();
|
|
46
|
+
i0.ɵɵtextInterpolate(ctx_r1.RecordDisplayName);
|
|
47
|
+
} }
|
|
48
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
49
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
50
|
+
i0.ɵɵelementStart(0, "div", 5)(1, "div", 12)(2, "div", 13);
|
|
51
|
+
i0.ɵɵelement(3, "i", 14);
|
|
52
|
+
i0.ɵɵelementStart(4, "span");
|
|
53
|
+
i0.ɵɵtext(5);
|
|
54
|
+
i0.ɵɵelementEnd();
|
|
55
|
+
i0.ɵɵconditionalCreate(6, MjRecordMicroViewComponent_ng_template_2_Conditional_0_Conditional_6_Template, 2, 1, "span", 15);
|
|
56
|
+
i0.ɵɵelementEnd();
|
|
57
|
+
i0.ɵɵelementStart(7, "div", 16);
|
|
58
|
+
i0.ɵɵelement(8, "i", 17);
|
|
59
|
+
i0.ɵɵelementStart(9, "span");
|
|
60
|
+
i0.ɵɵtext(10);
|
|
61
|
+
i0.ɵɵelementEnd()()();
|
|
62
|
+
i0.ɵɵelementStart(11, "div", 18)(12, "button", 19);
|
|
63
|
+
i0.ɵɵlistener("click", function MjRecordMicroViewComponent_ng_template_2_Conditional_0_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenRecord()); });
|
|
64
|
+
i0.ɵɵelement(13, "i", 20);
|
|
65
|
+
i0.ɵɵtext(14, " Open ");
|
|
66
|
+
i0.ɵɵelementEnd();
|
|
67
|
+
i0.ɵɵelementStart(15, "button", 21);
|
|
68
|
+
i0.ɵɵlistener("click", function MjRecordMicroViewComponent_ng_template_2_Conditional_0_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnClose()); });
|
|
69
|
+
i0.ɵɵelement(16, "i", 22);
|
|
70
|
+
i0.ɵɵelementEnd()()();
|
|
71
|
+
} if (rf & 2) {
|
|
72
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
73
|
+
i0.ɵɵadvance(3);
|
|
74
|
+
i0.ɵɵclassMap(ctx_r1.EntityIcon);
|
|
75
|
+
i0.ɵɵadvance(2);
|
|
76
|
+
i0.ɵɵtextInterpolate(ctx_r1.Data.EntityName);
|
|
77
|
+
i0.ɵɵadvance();
|
|
78
|
+
i0.ɵɵconditional(ctx_r1.RecordDisplayName ? 6 : -1);
|
|
79
|
+
i0.ɵɵadvance(4);
|
|
80
|
+
i0.ɵɵtextInterpolate(ctx_r1.DisplayRecordID);
|
|
81
|
+
} }
|
|
82
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
83
|
+
i0.ɵɵelementStart(0, "span", 15);
|
|
84
|
+
i0.ɵɵtext(1);
|
|
85
|
+
i0.ɵɵelementEnd();
|
|
86
|
+
} if (rf & 2) {
|
|
87
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
88
|
+
i0.ɵɵadvance();
|
|
89
|
+
i0.ɵɵtextInterpolate(ctx_r1.RecordDisplayName);
|
|
90
|
+
} }
|
|
91
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
92
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
93
|
+
i0.ɵɵelementStart(0, "div", 6)(1, "div", 23)(2, "div", 13);
|
|
94
|
+
i0.ɵɵelement(3, "i", 14);
|
|
95
|
+
i0.ɵɵelementStart(4, "span");
|
|
96
|
+
i0.ɵɵtext(5);
|
|
97
|
+
i0.ɵɵelementEnd();
|
|
98
|
+
i0.ɵɵconditionalCreate(6, MjRecordMicroViewComponent_ng_template_2_Conditional_1_Conditional_6_Template, 2, 1, "span", 15);
|
|
99
|
+
i0.ɵɵelementEnd();
|
|
100
|
+
i0.ɵɵelementStart(7, "div", 16);
|
|
101
|
+
i0.ɵɵelement(8, "i", 17);
|
|
102
|
+
i0.ɵɵelementStart(9, "span");
|
|
103
|
+
i0.ɵɵtext(10);
|
|
104
|
+
i0.ɵɵelementEnd()()();
|
|
105
|
+
i0.ɵɵelementStart(11, "button", 19);
|
|
106
|
+
i0.ɵɵlistener("click", function MjRecordMicroViewComponent_ng_template_2_Conditional_1_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenRecord()); });
|
|
107
|
+
i0.ɵɵelement(12, "i", 20);
|
|
108
|
+
i0.ɵɵtext(13, " Open ");
|
|
109
|
+
i0.ɵɵelementEnd()();
|
|
110
|
+
} if (rf & 2) {
|
|
111
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
112
|
+
i0.ɵɵadvance(3);
|
|
113
|
+
i0.ɵɵclassMap(ctx_r1.EntityIcon);
|
|
114
|
+
i0.ɵɵadvance(2);
|
|
115
|
+
i0.ɵɵtextInterpolate(ctx_r1.Data.EntityName);
|
|
116
|
+
i0.ɵɵadvance();
|
|
117
|
+
i0.ɵɵconditional(ctx_r1.RecordDisplayName ? 6 : -1);
|
|
118
|
+
i0.ɵɵadvance(4);
|
|
119
|
+
i0.ɵɵtextInterpolate(ctx_r1.DisplayRecordID);
|
|
120
|
+
} }
|
|
121
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
122
|
+
i0.ɵɵelement(0, "mj-loading", 8);
|
|
123
|
+
} }
|
|
124
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
125
|
+
i0.ɵɵelementStart(0, "div", 9);
|
|
126
|
+
i0.ɵɵelement(1, "i", 24);
|
|
127
|
+
i0.ɵɵelementStart(2, "span");
|
|
128
|
+
i0.ɵɵtext(3);
|
|
129
|
+
i0.ɵɵelementEnd()();
|
|
130
|
+
} if (rf & 2) {
|
|
131
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
132
|
+
i0.ɵɵadvance(3);
|
|
133
|
+
i0.ɵɵtextInterpolate(ctx_r1.ErrorMessage);
|
|
134
|
+
} }
|
|
135
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
136
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
137
|
+
i0.ɵɵelementStart(0, "div", 25)(1, "label", 30)(2, "input", 31);
|
|
138
|
+
i0.ɵɵlistener("change", function MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_1_Template_input_change_2_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleShowNulls()); });
|
|
139
|
+
i0.ɵɵelementEnd();
|
|
140
|
+
i0.ɵɵelementStart(3, "span", 32);
|
|
141
|
+
i0.ɵɵtext(4);
|
|
142
|
+
i0.ɵɵelementEnd()()();
|
|
143
|
+
} if (rf & 2) {
|
|
144
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
145
|
+
i0.ɵɵadvance(2);
|
|
146
|
+
i0.ɵɵproperty("checked", ctx_r1.ShowNullValues);
|
|
147
|
+
i0.ɵɵadvance(2);
|
|
148
|
+
i0.ɵɵtextInterpolate1("Show null values (", ctx_r1.HiddenNullCount, ")");
|
|
149
|
+
} }
|
|
150
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
151
|
+
i0.ɵɵelementStart(0, "span", 28);
|
|
152
|
+
i0.ɵɵtext(1, "Value");
|
|
153
|
+
i0.ɵɵelementEnd();
|
|
154
|
+
} }
|
|
155
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
156
|
+
i0.ɵɵelementStart(0, "span", 33);
|
|
157
|
+
i0.ɵɵtext(1, "Old");
|
|
158
|
+
i0.ɵɵelementEnd();
|
|
159
|
+
i0.ɵɵelementStart(2, "span", 34);
|
|
160
|
+
i0.ɵɵtext(3, "New");
|
|
161
|
+
i0.ɵɵelementEnd();
|
|
162
|
+
} }
|
|
163
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
164
|
+
i0.ɵɵelement(0, "i", 42);
|
|
165
|
+
i0.ɵɵelementStart(1, "span", 43);
|
|
166
|
+
i0.ɵɵtext(2);
|
|
167
|
+
i0.ɵɵelementEnd();
|
|
168
|
+
} if (rf & 2) {
|
|
169
|
+
const field_r7 = i0.ɵɵnextContext(2).$implicit;
|
|
170
|
+
i0.ɵɵclassMap(field_r7.BooleanValue ? "fa-solid fa-square-check mf-bool-true" : "fa-regular fa-square mf-bool-false");
|
|
171
|
+
i0.ɵɵadvance(2);
|
|
172
|
+
i0.ɵɵtextInterpolate(field_r7.BooleanValue ? "Yes" : "No");
|
|
173
|
+
} }
|
|
174
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
175
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
176
|
+
i0.ɵɵelementStart(0, "a", 44);
|
|
177
|
+
i0.ɵɵlistener("click", function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_2_Template_a_click_0_listener($event) { i0.ɵɵrestoreView(_r8); const field_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnEntityLinkClicked($event, field_r7)); });
|
|
178
|
+
i0.ɵɵtext(1);
|
|
179
|
+
i0.ɵɵelementStart(2, "span", 45);
|
|
180
|
+
i0.ɵɵtext(3);
|
|
181
|
+
i0.ɵɵpipe(4, "slice");
|
|
182
|
+
i0.ɵɵelementEnd();
|
|
183
|
+
i0.ɵɵelement(5, "i", 46);
|
|
184
|
+
i0.ɵɵelementEnd();
|
|
185
|
+
} if (rf & 2) {
|
|
186
|
+
const field_r7 = i0.ɵɵnextContext(2).$implicit;
|
|
187
|
+
i0.ɵɵproperty("title", field_r7.ForeignKeyEntityName + ": " + field_r7.ForeignKeyRecordId);
|
|
188
|
+
i0.ɵɵadvance();
|
|
189
|
+
i0.ɵɵtextInterpolate1(" ", field_r7.ForeignKeyDisplayValue, " ");
|
|
190
|
+
i0.ɵɵadvance(2);
|
|
191
|
+
i0.ɵɵtextInterpolate1("(", i0.ɵɵpipeBind3(4, 3, field_r7.ForeignKeyRecordId, 0, 8), "...)");
|
|
192
|
+
} }
|
|
193
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
194
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
195
|
+
i0.ɵɵelementStart(0, "a", 44);
|
|
196
|
+
i0.ɵɵlistener("click", function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_3_Template_a_click_0_listener($event) { i0.ɵɵrestoreView(_r9); const field_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnEntityLinkClicked($event, field_r7)); });
|
|
197
|
+
i0.ɵɵtext(1);
|
|
198
|
+
i0.ɵɵelement(2, "i", 46);
|
|
199
|
+
i0.ɵɵelementEnd();
|
|
200
|
+
} if (rf & 2) {
|
|
201
|
+
const field_r7 = i0.ɵɵnextContext(2).$implicit;
|
|
202
|
+
i0.ɵɵproperty("title", "Open " + field_r7.ForeignKeyEntityName);
|
|
203
|
+
i0.ɵɵadvance();
|
|
204
|
+
i0.ɵɵtextInterpolate1(" ", field_r7.Value, " ");
|
|
205
|
+
} }
|
|
206
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
207
|
+
i0.ɵɵelementStart(0, "pre", 41);
|
|
208
|
+
i0.ɵɵtext(1);
|
|
209
|
+
i0.ɵɵelementEnd();
|
|
210
|
+
} if (rf & 2) {
|
|
211
|
+
const field_r7 = i0.ɵɵnextContext(2).$implicit;
|
|
212
|
+
i0.ɵɵadvance();
|
|
213
|
+
i0.ɵɵtextInterpolate(field_r7.Value);
|
|
214
|
+
} }
|
|
215
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
216
|
+
i0.ɵɵtext(0);
|
|
217
|
+
} if (rf & 2) {
|
|
218
|
+
const field_r7 = i0.ɵɵnextContext(2).$implicit;
|
|
219
|
+
i0.ɵɵtextInterpolate1(" ", field_r7.Value, " ");
|
|
220
|
+
} }
|
|
221
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
222
|
+
i0.ɵɵelementStart(0, "span", 39);
|
|
223
|
+
i0.ɵɵconditionalCreate(1, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_1_Template, 3, 3);
|
|
224
|
+
i0.ɵɵconditionalCreate(2, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_2_Template, 6, 7, "a", 40);
|
|
225
|
+
i0.ɵɵconditionalCreate(3, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_3_Template, 3, 2, "a", 40);
|
|
226
|
+
i0.ɵɵconditionalCreate(4, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_4_Template, 2, 1, "pre", 41);
|
|
227
|
+
i0.ɵɵconditionalCreate(5, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Conditional_5_Template, 1, 1);
|
|
228
|
+
i0.ɵɵelementEnd();
|
|
229
|
+
} if (rf & 2) {
|
|
230
|
+
const field_r7 = i0.ɵɵnextContext().$implicit;
|
|
231
|
+
i0.ɵɵproperty("title", field_r7.Value);
|
|
232
|
+
i0.ɵɵadvance();
|
|
233
|
+
i0.ɵɵconditional(field_r7.IsBoolean && !field_r7.IsNull ? 1 : -1);
|
|
234
|
+
i0.ɵɵadvance();
|
|
235
|
+
i0.ɵɵconditional(!field_r7.IsBoolean && field_r7.ForeignKeyEntityName && field_r7.ForeignKeyDisplayValue ? 2 : -1);
|
|
236
|
+
i0.ɵɵadvance();
|
|
237
|
+
i0.ɵɵconditional(!field_r7.IsBoolean && field_r7.ForeignKeyEntityName && !field_r7.ForeignKeyDisplayValue ? 3 : -1);
|
|
238
|
+
i0.ɵɵadvance();
|
|
239
|
+
i0.ɵɵconditional(!field_r7.IsBoolean && !field_r7.ForeignKeyEntityName && field_r7.IsJson ? 4 : -1);
|
|
240
|
+
i0.ɵɵadvance();
|
|
241
|
+
i0.ɵɵconditional(!field_r7.IsBoolean && !field_r7.ForeignKeyEntityName && !field_r7.IsJson ? 5 : -1);
|
|
242
|
+
} }
|
|
243
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
244
|
+
i0.ɵɵelementStart(0, "span", 47);
|
|
245
|
+
i0.ɵɵtext(1);
|
|
246
|
+
i0.ɵɵelementEnd();
|
|
247
|
+
i0.ɵɵelementStart(2, "span", 48);
|
|
248
|
+
i0.ɵɵtext(3);
|
|
249
|
+
i0.ɵɵelementEnd();
|
|
250
|
+
} if (rf & 2) {
|
|
251
|
+
const field_r7 = i0.ɵɵnextContext().$implicit;
|
|
252
|
+
i0.ɵɵproperty("title", field_r7.OldValue);
|
|
253
|
+
i0.ɵɵadvance();
|
|
254
|
+
i0.ɵɵtextInterpolate1(" ", field_r7.OldValue || field_r7.Value, " ");
|
|
255
|
+
i0.ɵɵadvance();
|
|
256
|
+
i0.ɵɵproperty("title", field_r7.Value);
|
|
257
|
+
i0.ɵɵadvance();
|
|
258
|
+
i0.ɵɵtextInterpolate1(" ", field_r7.Value, " ");
|
|
259
|
+
} }
|
|
260
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
261
|
+
i0.ɵɵelementStart(0, "div", 35)(1, "span", 36);
|
|
262
|
+
i0.ɵɵelement(2, "i", 37);
|
|
263
|
+
i0.ɵɵelementStart(3, "span", 38);
|
|
264
|
+
i0.ɵɵtext(4);
|
|
265
|
+
i0.ɵɵelementEnd()();
|
|
266
|
+
i0.ɵɵconditionalCreate(5, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_5_Template, 6, 6, "span", 39);
|
|
267
|
+
i0.ɵɵconditionalCreate(6, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Conditional_6_Template, 4, 4);
|
|
268
|
+
i0.ɵɵelementEnd();
|
|
269
|
+
} if (rf & 2) {
|
|
270
|
+
const field_r7 = ctx.$implicit;
|
|
271
|
+
const ɵ$index_123_r10 = ctx.$index;
|
|
272
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
273
|
+
i0.ɵɵclassProp("odd", ɵ$index_123_r10 % 2 !== 0);
|
|
274
|
+
i0.ɵɵproperty("ngClass", field_r7.DiffClass);
|
|
275
|
+
i0.ɵɵadvance();
|
|
276
|
+
i0.ɵɵproperty("title", field_r7.Description);
|
|
277
|
+
i0.ɵɵadvance();
|
|
278
|
+
i0.ɵɵclassMap(ctx_r1.GetTypeIcon(field_r7.Type));
|
|
279
|
+
i0.ɵɵadvance(2);
|
|
280
|
+
i0.ɵɵtextInterpolate(field_r7.DisplayName);
|
|
281
|
+
i0.ɵɵadvance();
|
|
282
|
+
i0.ɵɵconditional(!ctx_r1.HasDiffs ? 5 : -1);
|
|
283
|
+
i0.ɵɵadvance();
|
|
284
|
+
i0.ɵɵconditional(ctx_r1.HasDiffs ? 6 : -1);
|
|
285
|
+
} }
|
|
286
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
287
|
+
i0.ɵɵelementStart(0, "div", 10);
|
|
288
|
+
i0.ɵɵconditionalCreate(1, MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_1_Template, 5, 2, "div", 25);
|
|
289
|
+
i0.ɵɵelementStart(2, "div", 26)(3, "span", 27);
|
|
290
|
+
i0.ɵɵtext(4, "Field");
|
|
291
|
+
i0.ɵɵelementEnd();
|
|
292
|
+
i0.ɵɵconditionalCreate(5, MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_5_Template, 2, 0, "span", 28);
|
|
293
|
+
i0.ɵɵconditionalCreate(6, MjRecordMicroViewComponent_ng_template_2_Conditional_5_Conditional_6_Template, 4, 0);
|
|
294
|
+
i0.ɵɵelementEnd();
|
|
295
|
+
i0.ɵɵrepeaterCreate(7, MjRecordMicroViewComponent_ng_template_2_Conditional_5_For_8_Template, 7, 9, "div", 29, i0.ɵɵrepeaterTrackByIdentity);
|
|
296
|
+
i0.ɵɵelementEnd();
|
|
297
|
+
} if (rf & 2) {
|
|
298
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
299
|
+
i0.ɵɵadvance();
|
|
300
|
+
i0.ɵɵconditional(ctx_r1.HiddenNullCount > 0 ? 1 : -1);
|
|
301
|
+
i0.ɵɵadvance(4);
|
|
302
|
+
i0.ɵɵconditional(!ctx_r1.HasDiffs ? 5 : -1);
|
|
303
|
+
i0.ɵɵadvance();
|
|
304
|
+
i0.ɵɵconditional(ctx_r1.HasDiffs ? 6 : -1);
|
|
305
|
+
i0.ɵɵadvance();
|
|
306
|
+
i0.ɵɵrepeater(ctx_r1.VisibleFields);
|
|
307
|
+
} }
|
|
308
|
+
function MjRecordMicroViewComponent_ng_template_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
309
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "p");
|
|
310
|
+
i0.ɵɵtext(2, "No field data available.");
|
|
311
|
+
i0.ɵɵelementEnd()();
|
|
312
|
+
} }
|
|
313
|
+
function MjRecordMicroViewComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
314
|
+
i0.ɵɵconditionalCreate(0, MjRecordMicroViewComponent_ng_template_2_Conditional_0_Template, 17, 5, "div", 5);
|
|
315
|
+
i0.ɵɵconditionalCreate(1, MjRecordMicroViewComponent_ng_template_2_Conditional_1_Template, 14, 5, "div", 6);
|
|
316
|
+
i0.ɵɵelementStart(2, "div", 7);
|
|
317
|
+
i0.ɵɵconditionalCreate(3, MjRecordMicroViewComponent_ng_template_2_Conditional_3_Template, 1, 0, "mj-loading", 8);
|
|
318
|
+
i0.ɵɵconditionalCreate(4, MjRecordMicroViewComponent_ng_template_2_Conditional_4_Template, 4, 1, "div", 9);
|
|
319
|
+
i0.ɵɵconditionalCreate(5, MjRecordMicroViewComponent_ng_template_2_Conditional_5_Template, 9, 3, "div", 10);
|
|
320
|
+
i0.ɵɵconditionalCreate(6, MjRecordMicroViewComponent_ng_template_2_Conditional_6_Template, 3, 0, "div", 11);
|
|
321
|
+
i0.ɵɵelementEnd();
|
|
322
|
+
} if (rf & 2) {
|
|
323
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
324
|
+
i0.ɵɵconditional(!ctx_r1.Inline ? 0 : -1);
|
|
325
|
+
i0.ɵɵadvance();
|
|
326
|
+
i0.ɵɵconditional(ctx_r1.Inline ? 1 : -1);
|
|
327
|
+
i0.ɵɵadvance();
|
|
328
|
+
i0.ɵɵclassProp("micro-content-inline", ctx_r1.Inline);
|
|
329
|
+
i0.ɵɵadvance();
|
|
330
|
+
i0.ɵɵconditional(ctx_r1.IsLoading ? 3 : -1);
|
|
331
|
+
i0.ɵɵadvance();
|
|
332
|
+
i0.ɵɵconditional(!ctx_r1.IsLoading && ctx_r1.ErrorMessage ? 4 : -1);
|
|
333
|
+
i0.ɵɵadvance();
|
|
334
|
+
i0.ɵɵconditional(!ctx_r1.IsLoading && !ctx_r1.ErrorMessage && ctx_r1.Fields.length > 0 ? 5 : -1);
|
|
335
|
+
i0.ɵɵadvance();
|
|
336
|
+
i0.ɵɵconditional(!ctx_r1.IsLoading && !ctx_r1.ErrorMessage && ctx_r1.Fields.length === 0 ? 6 : -1);
|
|
337
|
+
} }
|
|
338
|
+
export class MjRecordMicroViewComponent {
|
|
339
|
+
cdr;
|
|
340
|
+
Data;
|
|
341
|
+
Inline = false;
|
|
342
|
+
Close = new EventEmitter();
|
|
343
|
+
EntityLinkClick = new EventEmitter();
|
|
344
|
+
OpenRecord = new EventEmitter();
|
|
345
|
+
IsLoading = true;
|
|
346
|
+
IsVisible = false;
|
|
347
|
+
Fields = [];
|
|
348
|
+
ErrorMessage = '';
|
|
349
|
+
ShowNullValues = false;
|
|
350
|
+
/** Formatted display of the record primary key (simplified for single-value PKs) */
|
|
351
|
+
DisplayRecordID = '';
|
|
352
|
+
/** The value of the IsNameField for display in the header */
|
|
353
|
+
RecordDisplayName = '';
|
|
354
|
+
/** Icon CSS class from EntityInfo.Icon, falls back to 'fa-solid fa-table' */
|
|
355
|
+
EntityIcon = 'fa-solid fa-table';
|
|
356
|
+
metadata = new Metadata();
|
|
357
|
+
constructor(cdr) {
|
|
358
|
+
this.cdr = cdr;
|
|
359
|
+
}
|
|
360
|
+
ngOnInit() {
|
|
361
|
+
if (this.Inline) {
|
|
362
|
+
this.IsVisible = true;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
Promise.resolve().then(() => {
|
|
366
|
+
this.IsVisible = true;
|
|
367
|
+
this.cdr.markForCheck();
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
this.DisplayRecordID = this.formatRecordId(this.Data.RecordID);
|
|
371
|
+
this.loadRecordData();
|
|
372
|
+
}
|
|
373
|
+
OnEscapeKey() {
|
|
374
|
+
if (!this.Inline) {
|
|
375
|
+
this.OnClose();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
OnClose() {
|
|
379
|
+
if (this.Inline) {
|
|
380
|
+
this.Close.emit();
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
this.IsVisible = false;
|
|
384
|
+
this.cdr.markForCheck();
|
|
385
|
+
setTimeout(() => this.Close.emit(), 250);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
OnBackdropClick() {
|
|
389
|
+
this.OnClose();
|
|
390
|
+
}
|
|
391
|
+
GetTypeIcon(type) {
|
|
392
|
+
const icons = {
|
|
393
|
+
'uniqueidentifier': 'fa-solid fa-fingerprint',
|
|
394
|
+
'datetime': 'fa-solid fa-calendar',
|
|
395
|
+
'datetimeoffset': 'fa-solid fa-calendar',
|
|
396
|
+
'date': 'fa-solid fa-calendar-day',
|
|
397
|
+
'time': 'fa-solid fa-clock',
|
|
398
|
+
'bit': 'fa-solid fa-toggle-on',
|
|
399
|
+
'boolean': 'fa-solid fa-toggle-on',
|
|
400
|
+
'int': 'fa-solid fa-hashtag',
|
|
401
|
+
'bigint': 'fa-solid fa-hashtag',
|
|
402
|
+
'float': 'fa-solid fa-hashtag',
|
|
403
|
+
'decimal': 'fa-solid fa-hashtag',
|
|
404
|
+
'money': 'fa-solid fa-hashtag',
|
|
405
|
+
'number': 'fa-solid fa-hashtag',
|
|
406
|
+
'nvarchar': 'fa-solid fa-font',
|
|
407
|
+
'varchar': 'fa-solid fa-font',
|
|
408
|
+
'ntext': 'fa-solid fa-align-left',
|
|
409
|
+
'text': 'fa-solid fa-align-left',
|
|
410
|
+
'string': 'fa-solid fa-font',
|
|
411
|
+
'object': 'fa-solid fa-code',
|
|
412
|
+
'null': 'fa-solid fa-circle-xmark'
|
|
413
|
+
};
|
|
414
|
+
return icons[type.toLowerCase()] ?? 'fa-solid fa-font';
|
|
415
|
+
}
|
|
416
|
+
get HasDiffs() {
|
|
417
|
+
return this.Data.FieldDiffs != null && this.Data.FieldDiffs.length > 0;
|
|
418
|
+
}
|
|
419
|
+
get VisibleFields() {
|
|
420
|
+
if (this.ShowNullValues) {
|
|
421
|
+
return this.Fields;
|
|
422
|
+
}
|
|
423
|
+
return this.Fields.filter(f => !f.IsNull);
|
|
424
|
+
}
|
|
425
|
+
get HiddenNullCount() {
|
|
426
|
+
return this.Fields.filter(f => f.IsNull).length;
|
|
427
|
+
}
|
|
428
|
+
ToggleShowNulls() {
|
|
429
|
+
this.ShowNullValues = !this.ShowNullValues;
|
|
430
|
+
this.cdr.markForCheck();
|
|
431
|
+
}
|
|
432
|
+
OnEntityLinkClicked(event, field) {
|
|
433
|
+
event.stopPropagation();
|
|
434
|
+
if (field.ForeignKeyEntityName && field.ForeignKeyRecordId) {
|
|
435
|
+
const pkey = new CompositeKey([{ FieldName: 'ID', Value: field.ForeignKeyRecordId }]);
|
|
436
|
+
this.EntityLinkClick.emit({
|
|
437
|
+
EntityName: field.ForeignKeyEntityName,
|
|
438
|
+
RecordID: field.ForeignKeyRecordId,
|
|
439
|
+
CompositeKey: pkey
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
OnOpenRecord() {
|
|
444
|
+
if (this.Data.EntityName && this.Data.RecordID) {
|
|
445
|
+
const rawId = this.extractRawId(this.Data.RecordID);
|
|
446
|
+
const pkey = new CompositeKey([{ FieldName: 'ID', Value: rawId }]);
|
|
447
|
+
this.OpenRecord.emit({
|
|
448
|
+
EntityName: this.Data.EntityName,
|
|
449
|
+
RecordID: rawId,
|
|
450
|
+
CompositeKey: pkey
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
// =========================================================================
|
|
455
|
+
// Data loading
|
|
456
|
+
// =========================================================================
|
|
457
|
+
async loadRecordData() {
|
|
458
|
+
this.IsLoading = true;
|
|
459
|
+
this.cdr.markForCheck();
|
|
460
|
+
try {
|
|
461
|
+
let recordData = this.Data.FullRecordJSON;
|
|
462
|
+
if (!recordData && this.Data.RecordChangeID) {
|
|
463
|
+
recordData = await this.loadRecordChangeJson(this.Data.RecordChangeID);
|
|
464
|
+
}
|
|
465
|
+
if (recordData) {
|
|
466
|
+
const entityInfo = this.findEntityInfo();
|
|
467
|
+
this.EntityIcon = entityInfo?.Icon || 'fa-solid fa-table';
|
|
468
|
+
this.RecordDisplayName = this.extractNameFieldValue(entityInfo, recordData);
|
|
469
|
+
this.Fields = this.buildFieldList(recordData, entityInfo);
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
this.ErrorMessage = 'Unable to load record data.';
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
this.ErrorMessage = e instanceof Error ? e.message : 'Failed to load record data.';
|
|
477
|
+
}
|
|
478
|
+
finally {
|
|
479
|
+
this.IsLoading = false;
|
|
480
|
+
this.cdr.markForCheck();
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
async loadRecordChangeJson(changeId) {
|
|
484
|
+
const rv = new RunView();
|
|
485
|
+
const result = await rv.RunView({
|
|
486
|
+
EntityName: 'Record Changes',
|
|
487
|
+
ExtraFilter: `ID = '${changeId}'`,
|
|
488
|
+
Fields: ['FullRecordJSON'],
|
|
489
|
+
ResultType: 'simple'
|
|
490
|
+
});
|
|
491
|
+
if (result.Success && result.Results.length > 0) {
|
|
492
|
+
const json = result.Results[0].FullRecordJSON;
|
|
493
|
+
if (json) {
|
|
494
|
+
return JSON.parse(json);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
// =========================================================================
|
|
500
|
+
// Field building
|
|
501
|
+
// =========================================================================
|
|
502
|
+
buildFieldList(data, entityInfo) {
|
|
503
|
+
const diffMap = this.buildDiffMap();
|
|
504
|
+
const fkMap = this.buildForeignKeyMap(entityInfo, data);
|
|
505
|
+
const virtualFieldNames = this.getVirtualFieldNames(entityInfo);
|
|
506
|
+
const fields = [];
|
|
507
|
+
for (const [key, value] of Object.entries(data)) {
|
|
508
|
+
if (key.startsWith('__mj_'))
|
|
509
|
+
continue;
|
|
510
|
+
// Skip virtual fields that we've merged into their FK counterpart
|
|
511
|
+
if (virtualFieldNames.has(key))
|
|
512
|
+
continue;
|
|
513
|
+
const fieldMeta = entityInfo?.Fields.find(f => f.Name === key);
|
|
514
|
+
const diff = diffMap.get(key);
|
|
515
|
+
const fkInfo = fkMap.get(key);
|
|
516
|
+
const fieldType = fieldMeta?.Type ?? this.inferType(value);
|
|
517
|
+
const isBooleanField = this.isBooleanType(fieldType, value);
|
|
518
|
+
const isJsonField = this.isJsonValue(value);
|
|
519
|
+
fields.push({
|
|
520
|
+
Name: key,
|
|
521
|
+
DisplayName: fieldMeta?.DisplayNameOrName ?? key,
|
|
522
|
+
Value: this.formatValue(value, isJsonField),
|
|
523
|
+
Type: fieldType,
|
|
524
|
+
Description: fieldMeta?.Description ?? '',
|
|
525
|
+
DiffClass: diff?.ChangeType ? `diff-${diff.ChangeType.toLowerCase()}` : '',
|
|
526
|
+
OldValue: diff?.OldValue ?? '',
|
|
527
|
+
IsNull: value == null,
|
|
528
|
+
IsBoolean: isBooleanField,
|
|
529
|
+
BooleanValue: this.toBooleanValue(value),
|
|
530
|
+
IsJson: isJsonField,
|
|
531
|
+
Sequence: fieldMeta?.Sequence ?? 9999,
|
|
532
|
+
ForeignKeyDisplayValue: fkInfo?.DisplayValue ?? '',
|
|
533
|
+
ForeignKeyEntityName: fkInfo?.EntityName ?? '',
|
|
534
|
+
ForeignKeyRecordId: fkInfo?.RecordId ?? ''
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
return fields.sort((a, b) => a.Sequence - b.Sequence);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Find the entity's NameField (uses EntityInfo.NameField getter which checks
|
|
541
|
+
* IsNameField first, then falls back to a field called "Name").
|
|
542
|
+
*/
|
|
543
|
+
extractNameFieldValue(entityInfo, data) {
|
|
544
|
+
if (!entityInfo)
|
|
545
|
+
return '';
|
|
546
|
+
const nameField = entityInfo.NameField;
|
|
547
|
+
if (nameField && data[nameField.Name] != null) {
|
|
548
|
+
return String(data[nameField.Name]);
|
|
549
|
+
}
|
|
550
|
+
return '';
|
|
551
|
+
}
|
|
552
|
+
findEntityInfo() {
|
|
553
|
+
if (this.Data.EntityName && this.Data.EntityName !== 'Unknown') {
|
|
554
|
+
return this.metadata.Entities.find(e => e.Name === this.Data.EntityName);
|
|
555
|
+
}
|
|
556
|
+
if (this.Data.EntityID) {
|
|
557
|
+
return this.metadata.Entities.find(e => e.ID === this.Data.EntityID);
|
|
558
|
+
}
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
buildDiffMap() {
|
|
562
|
+
const map = new Map();
|
|
563
|
+
if (this.Data.FieldDiffs) {
|
|
564
|
+
for (const diff of this.Data.FieldDiffs) {
|
|
565
|
+
map.set(diff.FieldName, { ChangeType: diff.ChangeType, OldValue: diff.OldValue });
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return map;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Build a map of FK field name -> { DisplayValue, EntityName, RecordId }
|
|
572
|
+
* by matching FK fields to their associated virtual (display) fields.
|
|
573
|
+
*/
|
|
574
|
+
buildForeignKeyMap(entityInfo, data) {
|
|
575
|
+
const map = new Map();
|
|
576
|
+
if (!entityInfo)
|
|
577
|
+
return map;
|
|
578
|
+
for (const field of entityInfo.Fields) {
|
|
579
|
+
if (!field.RelatedEntityID || field.Name === 'ID')
|
|
580
|
+
continue;
|
|
581
|
+
// Find the related entity name
|
|
582
|
+
const relatedEntity = this.metadata.Entities.find(e => e.ID === field.RelatedEntityID);
|
|
583
|
+
if (!relatedEntity)
|
|
584
|
+
continue;
|
|
585
|
+
const fkValue = data[field.Name];
|
|
586
|
+
if (fkValue == null)
|
|
587
|
+
continue;
|
|
588
|
+
// Find display value from the associated virtual field
|
|
589
|
+
const displayValue = this.findFkDisplayValue(entityInfo, field.Name, data);
|
|
590
|
+
map.set(field.Name, {
|
|
591
|
+
DisplayValue: displayValue,
|
|
592
|
+
EntityName: relatedEntity.Name,
|
|
593
|
+
RecordId: String(fkValue)
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
return map;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Find the display value for a FK field by checking multiple strategies:
|
|
600
|
+
* 1. Look for a virtual field with RelatedEntityNameFieldMap pointing to this FK
|
|
601
|
+
* 2. Look for any virtual field whose name is derived from the FK name
|
|
602
|
+
* 3. Scan data keys for common naming patterns (e.g., "TypeID" -> "Type")
|
|
603
|
+
*/
|
|
604
|
+
findFkDisplayValue(entityInfo, fkFieldName, data) {
|
|
605
|
+
// Strategy 1: Metadata-linked virtual field via RelatedEntityNameFieldMap
|
|
606
|
+
const linkedVirtual = entityInfo.Fields.find(f => f.RelatedEntityNameFieldMap === fkFieldName && f.IsVirtual);
|
|
607
|
+
if (linkedVirtual && data[linkedVirtual.Name] != null) {
|
|
608
|
+
return String(data[linkedVirtual.Name]);
|
|
609
|
+
}
|
|
610
|
+
// Strategy 2: Find any virtual field that looks like a display field for this FK
|
|
611
|
+
// by checking all virtual fields and matching via naming patterns
|
|
612
|
+
const virtualFields = entityInfo.Fields.filter(f => f.IsVirtual);
|
|
613
|
+
for (const vf of virtualFields) {
|
|
614
|
+
// Check if this virtual field's RelatedEntityNameFieldMap matches (case-insensitive)
|
|
615
|
+
if (vf.RelatedEntityNameFieldMap &&
|
|
616
|
+
vf.RelatedEntityNameFieldMap.toLowerCase() === fkFieldName.toLowerCase() &&
|
|
617
|
+
data[vf.Name] != null) {
|
|
618
|
+
return String(data[vf.Name]);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
// Strategy 3: Try common naming conventions in the data itself
|
|
622
|
+
// e.g., "TypeID" -> look for "Type" key in data
|
|
623
|
+
// "OwnerUserID" -> look for "Owner User" or "OwnerUser"
|
|
624
|
+
// Strip trailing "ID" from the FK name and try variations
|
|
625
|
+
if (fkFieldName.endsWith('ID') && fkFieldName.length > 2) {
|
|
626
|
+
const baseName = fkFieldName.slice(0, -2);
|
|
627
|
+
// Direct match in data (e.g., "CategoryID" -> "Category")
|
|
628
|
+
if (data[baseName] != null && typeof data[baseName] === 'string' &&
|
|
629
|
+
!this.looksLikeGuid(data[baseName])) {
|
|
630
|
+
return String(data[baseName]);
|
|
631
|
+
}
|
|
632
|
+
// Try with space before capitals (e.g., "OwnerUserID" -> "Owner User")
|
|
633
|
+
const spacedName = baseName.replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
634
|
+
if (spacedName !== baseName && data[spacedName] != null &&
|
|
635
|
+
typeof data[spacedName] === 'string' &&
|
|
636
|
+
!this.looksLikeGuid(data[spacedName])) {
|
|
637
|
+
return String(data[spacedName]);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
return '';
|
|
641
|
+
}
|
|
642
|
+
/** Quick check if a string looks like a GUID (to avoid using GUIDs as display values). */
|
|
643
|
+
looksLikeGuid(value) {
|
|
644
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Get the set of virtual field names so we can skip them in the main field list.
|
|
648
|
+
* Virtual fields are display-only fields whose values are merged into FK rows.
|
|
649
|
+
* We skip ALL virtual fields — not just ones with RelatedEntityNameFieldMap —
|
|
650
|
+
* because they are derived/computed and don't represent stored data.
|
|
651
|
+
*/
|
|
652
|
+
getVirtualFieldNames(entityInfo) {
|
|
653
|
+
const names = new Set();
|
|
654
|
+
if (!entityInfo)
|
|
655
|
+
return names;
|
|
656
|
+
for (const field of entityInfo.Fields) {
|
|
657
|
+
if (field.IsVirtual) {
|
|
658
|
+
names.add(field.Name);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return names;
|
|
662
|
+
}
|
|
663
|
+
// =========================================================================
|
|
664
|
+
// Record ID formatting
|
|
665
|
+
// =========================================================================
|
|
666
|
+
/**
|
|
667
|
+
* For single-value PKs like "ID|<uuid>", extract just the uuid.
|
|
668
|
+
* For composite keys, show the full concatenated string.
|
|
669
|
+
*/
|
|
670
|
+
formatRecordId(recordId) {
|
|
671
|
+
if (!recordId)
|
|
672
|
+
return '';
|
|
673
|
+
const parts = recordId.split('||');
|
|
674
|
+
if (parts.length === 1) {
|
|
675
|
+
const singleParts = recordId.split('|');
|
|
676
|
+
if (singleParts.length === 2) {
|
|
677
|
+
return singleParts[1];
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return recordId;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Extract the raw ID value from a potentially formatted record ID string.
|
|
684
|
+
*/
|
|
685
|
+
extractRawId(recordId) {
|
|
686
|
+
if (!recordId)
|
|
687
|
+
return '';
|
|
688
|
+
const parts = recordId.split('||');
|
|
689
|
+
if (parts.length === 1) {
|
|
690
|
+
const singleParts = recordId.split('|');
|
|
691
|
+
if (singleParts.length === 2) {
|
|
692
|
+
return singleParts[1];
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return recordId;
|
|
696
|
+
}
|
|
697
|
+
// =========================================================================
|
|
698
|
+
// Type helpers
|
|
699
|
+
// =========================================================================
|
|
700
|
+
isBooleanType(type, value) {
|
|
701
|
+
const t = type.toLowerCase();
|
|
702
|
+
if (t === 'bit' || t === 'boolean')
|
|
703
|
+
return true;
|
|
704
|
+
if (value === true || value === false)
|
|
705
|
+
return true;
|
|
706
|
+
return false;
|
|
707
|
+
}
|
|
708
|
+
toBooleanValue(value) {
|
|
709
|
+
if (value === true || value === 1 || value === '1' || value === 'true')
|
|
710
|
+
return true;
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
isJsonValue(value) {
|
|
714
|
+
if (typeof value === 'object' && value != null)
|
|
715
|
+
return true;
|
|
716
|
+
if (typeof value === 'string') {
|
|
717
|
+
const trimmed = value.trim();
|
|
718
|
+
return (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
719
|
+
(trimmed.startsWith('[') && trimmed.endsWith(']'));
|
|
720
|
+
}
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
723
|
+
// =========================================================================
|
|
724
|
+
// Formatting helpers
|
|
725
|
+
// =========================================================================
|
|
726
|
+
formatValue(value, isJson) {
|
|
727
|
+
if (value == null)
|
|
728
|
+
return 'null';
|
|
729
|
+
if (typeof value === 'boolean')
|
|
730
|
+
return value ? 'true' : 'false';
|
|
731
|
+
if (typeof value === 'number')
|
|
732
|
+
return String(value);
|
|
733
|
+
if (typeof value === 'string') {
|
|
734
|
+
if (this.isDateString(value))
|
|
735
|
+
return this.formatDate(value);
|
|
736
|
+
// Try to pretty-print JSON strings
|
|
737
|
+
if (isJson)
|
|
738
|
+
return this.formatJsonString(value);
|
|
739
|
+
if (value.length > 300)
|
|
740
|
+
return value.substring(0, 300) + '...';
|
|
741
|
+
return value;
|
|
742
|
+
}
|
|
743
|
+
if (typeof value === 'object') {
|
|
744
|
+
try {
|
|
745
|
+
return JSON.stringify(value, null, 2);
|
|
746
|
+
}
|
|
747
|
+
catch {
|
|
748
|
+
return String(value);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return String(value);
|
|
752
|
+
}
|
|
753
|
+
formatJsonString(value) {
|
|
754
|
+
try {
|
|
755
|
+
const parsed = JSON.parse(value);
|
|
756
|
+
return JSON.stringify(parsed, null, 2);
|
|
757
|
+
}
|
|
758
|
+
catch {
|
|
759
|
+
return value;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
isDateString(value) {
|
|
763
|
+
return /^\d{4}-\d{2}-\d{2}T/.test(value);
|
|
764
|
+
}
|
|
765
|
+
formatDate(value) {
|
|
766
|
+
try {
|
|
767
|
+
const d = new Date(value);
|
|
768
|
+
return d.toLocaleDateString('en-US', {
|
|
769
|
+
month: 'short', day: 'numeric', year: 'numeric',
|
|
770
|
+
hour: '2-digit', minute: '2-digit'
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
catch {
|
|
774
|
+
return value;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
inferType(value) {
|
|
778
|
+
if (value == null)
|
|
779
|
+
return 'null';
|
|
780
|
+
if (typeof value === 'boolean')
|
|
781
|
+
return 'bit';
|
|
782
|
+
if (typeof value === 'number')
|
|
783
|
+
return 'int';
|
|
784
|
+
if (typeof value === 'string') {
|
|
785
|
+
if (this.isDateString(value))
|
|
786
|
+
return 'datetime';
|
|
787
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value))
|
|
788
|
+
return 'uniqueidentifier';
|
|
789
|
+
return 'nvarchar';
|
|
790
|
+
}
|
|
791
|
+
return 'object';
|
|
792
|
+
}
|
|
793
|
+
static ɵfac = function MjRecordMicroViewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MjRecordMicroViewComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
794
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MjRecordMicroViewComponent, selectors: [["mj-record-micro-view"]], hostBindings: function MjRecordMicroViewComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
795
|
+
i0.ɵɵlistener("keydown.escape", function MjRecordMicroViewComponent_keydown_escape_HostBindingHandler() { return ctx.OnEscapeKey(); }, i0.ɵɵresolveDocument);
|
|
796
|
+
} }, inputs: { Data: "Data", Inline: "Inline" }, outputs: { Close: "Close", EntityLinkClick: "EntityLinkClick", OpenRecord: "OpenRecord" }, standalone: false, decls: 4, vars: 2, consts: [["microContent", ""], [1, "micro-inline"], [1, "micro-backdrop", 3, "click"], [1, "micro-panel"], [4, "ngTemplateOutlet"], [1, "micro-header"], [1, "micro-inline-header"], [1, "micro-content"], ["text", "Loading record data..."], [1, "micro-error"], [1, "micro-fields"], [1, "micro-empty"], [1, "micro-header-info"], [1, "micro-entity"], [1, "micro-entity-icon"], [1, "micro-record-name"], [1, "micro-record-id"], [1, "fa-solid", "fa-fingerprint"], [1, "micro-header-actions"], ["title", "Open this record", 1, "micro-open-btn", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "micro-close", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "micro-header-left"], [1, "fa-solid", "fa-circle-exclamation"], [1, "micro-toolbar"], [1, "micro-field-header"], [1, "mf-col-name"], [1, "mf-col-value"], [1, "micro-field-row", 3, "odd", "ngClass"], [1, "null-toggle"], ["type", "checkbox", 3, "change", "checked"], [1, "null-toggle-label"], [1, "mf-col-old"], [1, "mf-col-new"], [1, "micro-field-row", 3, "ngClass"], [1, "mf-col-name", 3, "title"], [1, "mf-type-icon"], [1, "mf-field-name"], [1, "mf-col-value", 3, "title"], [1, "mf-fk-link", 3, "title"], [1, "mf-json-value"], [1, "mf-bool-icon"], [1, "mf-bool-label"], [1, "mf-fk-link", 3, "click", "title"], [1, "mf-fk-id"], [1, "fa-solid", "fa-arrow-up-right-from-square", "mf-fk-icon"], [1, "mf-col-old", 3, "title"], [1, "mf-col-new", 3, "title"]], template: function MjRecordMicroViewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
797
|
+
i0.ɵɵconditionalCreate(0, MjRecordMicroViewComponent_Conditional_0_Template, 3, 5);
|
|
798
|
+
i0.ɵɵconditionalCreate(1, MjRecordMicroViewComponent_Conditional_1_Template, 2, 1, "div", 1);
|
|
799
|
+
i0.ɵɵtemplate(2, MjRecordMicroViewComponent_ng_template_2_Template, 7, 8, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
800
|
+
} if (rf & 2) {
|
|
801
|
+
i0.ɵɵconditional(!ctx.Inline ? 0 : -1);
|
|
802
|
+
i0.ɵɵadvance();
|
|
803
|
+
i0.ɵɵconditional(ctx.Inline ? 1 : -1);
|
|
804
|
+
} }, dependencies: [i1.NgClass, i1.NgTemplateOutlet, i2.LoadingComponent, i1.SlicePipe], styles: ["\n\n\n\n\n\n\n.micro-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0);\n z-index: 1100;\n transition: background 0.25s ease;\n pointer-events: none;\n}\n\n.micro-backdrop.visible[_ngcontent-%COMP%] {\n background: rgba(0, 0, 0, 0.15);\n pointer-events: auto;\n}\n\n.micro-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 480px;\n max-width: 90vw;\n height: 100vh;\n background: var(--card-background, #ffffff);\n box-shadow: -6px 0 24px rgba(0, 0, 0, 0.1);\n z-index: 1101;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.micro-panel.visible[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n\n\n\n\n\n\n\n.micro-inline[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.micro-inline-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 16px 24px;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n flex-shrink: 0;\n}\n\n.micro-header-left[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.micro-content-inline[_ngcontent-%COMP%] {\n padding: 0;\n}\n\n\n\n\n\n\n\n\n.micro-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n flex-shrink: 0;\n}\n\n.micro-header-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.micro-header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.micro-entity[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 15px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n}\n\n.micro-entity-icon[_ngcontent-%COMP%] {\n color: #3b82f6;\n}\n\n\n\n.micro-record-name[_ngcontent-%COMP%] {\n color: #6366f1;\n font-weight: 700;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.micro-record-id[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--text-tertiary, #9ca3af);\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.micro-record-id[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n\n\n.micro-open-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 6px 12px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 6px;\n color: #3b82f6;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.micro-open-btn[_ngcontent-%COMP%]:hover {\n background: #3b82f6;\n color: white;\n border-color: #3b82f6;\n}\n\n.micro-open-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.micro-close[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: none;\n border: none;\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.micro-close[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n\n\n\n\n\n\n\n.micro-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.micro-error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 20px;\n margin: 0 20px;\n background: rgba(239, 68, 68, 0.06);\n border: 1px solid rgba(239, 68, 68, 0.15);\n border-radius: 8px;\n font-size: 13px;\n color: #ef4444;\n}\n\n\n\n.micro-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 8px 20px;\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.null-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n user-select: none;\n}\n\n.null-toggle[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 14px;\n height: 14px;\n accent-color: #6366f1;\n cursor: pointer;\n}\n\n.null-toggle-label[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n\n\n.micro-fields[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n.micro-field-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 180px 1fr;\n padding: 8px 20px;\n font-size: 11px;\n font-weight: 600;\n color: var(--text-tertiary, #9ca3af);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n position: sticky;\n top: 0;\n background: var(--card-background, #ffffff);\n z-index: 1;\n}\n\n.micro-field-header[_ngcontent-%COMP%]:has(.mf-col-old) {\n grid-template-columns: 160px 1fr 1fr;\n}\n\n.micro-field-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 180px 1fr;\n padding: 7px 20px;\n align-items: baseline;\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n transition: background 0.1s ease;\n}\n\n.micro-field-row[_ngcontent-%COMP%]:hover {\n background: var(--hover-background, #f9fafb);\n}\n\n.micro-field-row.odd[_ngcontent-%COMP%] {\n background: var(--hover-background, #fafafa);\n}\n\n.micro-field-row.odd[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n}\n\n\n\n.micro-field-row.diff-added[_ngcontent-%COMP%] {\n background: rgba(16, 185, 129, 0.04) !important;\n border-left: 3px solid #10b981;\n}\n\n.micro-field-row.diff-modified[_ngcontent-%COMP%] {\n background: rgba(245, 158, 11, 0.04) !important;\n border-left: 3px solid #f59e0b;\n}\n\n.micro-field-row.diff-removed[_ngcontent-%COMP%] {\n background: rgba(239, 68, 68, 0.04) !important;\n border-left: 3px solid #ef4444;\n}\n\n.micro-field-row[_ngcontent-%COMP%]:has(.mf-col-old) {\n grid-template-columns: 160px 1fr 1fr;\n}\n\n.mf-col-name[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n overflow: hidden;\n cursor: default;\n}\n\n.mf-type-icon[_ngcontent-%COMP%] {\n color: var(--text-tertiary, #d1d5db);\n font-size: 11px;\n width: 14px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.mf-field-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--text-primary, #1f2937);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mf-col-value[_ngcontent-%COMP%], \n.mf-col-old[_ngcontent-%COMP%], \n.mf-col-new[_ngcontent-%COMP%] {\n color: var(--text-secondary, #6b7280);\n word-break: break-word;\n line-height: 1.4;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 12px;\n}\n\n.mf-col-old[_ngcontent-%COMP%] {\n color: #ef4444;\n opacity: 0.7;\n text-decoration: line-through;\n}\n\n.mf-col-new[_ngcontent-%COMP%] {\n color: #10b981;\n}\n\n\n\n\n\n\n\n\n.mf-bool-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n vertical-align: middle;\n}\n\n.mf-bool-true[_ngcontent-%COMP%] {\n color: #10b981;\n}\n\n.mf-bool-false[_ngcontent-%COMP%] {\n color: var(--text-tertiary, #d1d5db);\n}\n\n.mf-bool-label[_ngcontent-%COMP%] {\n margin-left: 6px;\n font-family: inherit;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n\n\n\n\n\n\n\n.mf-fk-link[_ngcontent-%COMP%] {\n color: #3b82f6;\n cursor: pointer;\n text-decoration: none;\n font-family: inherit;\n font-size: inherit;\n transition: color 0.15s ease;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.mf-fk-link[_ngcontent-%COMP%]:hover {\n color: #2563eb;\n text-decoration: underline;\n}\n\n.mf-fk-id[_ngcontent-%COMP%] {\n color: var(--text-tertiary, #9ca3af);\n font-size: 10px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.mf-fk-icon[_ngcontent-%COMP%] {\n font-size: 9px;\n opacity: 0.6;\n transition: opacity 0.15s ease;\n}\n\n.mf-fk-link[_ngcontent-%COMP%]:hover .mf-fk-icon[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n\n\n\n\n\n.mf-json-value[_ngcontent-%COMP%] {\n margin: 0;\n padding: 8px 10px;\n background: var(--hover-background, #f9fafb);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 6px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 11px;\n line-height: 1.5;\n color: var(--text-secondary, #6b7280);\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n\n\n.micro-empty[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.micro-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--text-tertiary, #9ca3af);\n margin: 0;\n}\n\n\n\n\n\n\n\n\n.micro-inline[_ngcontent-%COMP%] .micro-field-header[_ngcontent-%COMP%], \n.micro-inline[_ngcontent-%COMP%] .micro-field-row[_ngcontent-%COMP%] {\n padding-left: 24px;\n padding-right: 24px;\n}\n\n.micro-inline[_ngcontent-%COMP%] .micro-toolbar[_ngcontent-%COMP%] {\n padding-left: 24px;\n padding-right: 24px;\n}\n\n@media (max-width: 600px) {\n .micro-field-header[_ngcontent-%COMP%], \n .micro-field-row[_ngcontent-%COMP%] {\n grid-template-columns: 120px 1fr;\n }\n\n .micro-field-header[_ngcontent-%COMP%]:has(.mf-col-old), \n .micro-field-row[_ngcontent-%COMP%]:has(.mf-col-old) {\n grid-template-columns: 100px 1fr 1fr;\n }\n\n .micro-record-name[_ngcontent-%COMP%] {\n max-width: 120px;\n }\n}"], changeDetection: 0 });
|
|
805
|
+
}
|
|
806
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MjRecordMicroViewComponent, [{
|
|
807
|
+
type: Component,
|
|
808
|
+
args: [{ standalone: false, selector: 'mj-record-micro-view', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Overlay mode -->\n@if (!Inline) {\n <div class=\"micro-backdrop\" [class.visible]=\"IsVisible\" (click)=\"OnBackdropClick()\"></div>\n <div class=\"micro-panel\" [class.visible]=\"IsVisible\">\n <ng-container *ngTemplateOutlet=\"microContent\"></ng-container>\n </div>\n}\n\n<!-- Inline mode (embedded in parent panel) -->\n@if (Inline) {\n <div class=\"micro-inline\">\n <ng-container *ngTemplateOutlet=\"microContent\"></ng-container>\n </div>\n}\n\n<!-- Shared content template -->\n<ng-template #microContent>\n <!-- Header (overlay mode only) -->\n @if (!Inline) {\n <div class=\"micro-header\">\n <div class=\"micro-header-info\">\n <div class=\"micro-entity\">\n <i [class]=\"EntityIcon\" class=\"micro-entity-icon\"></i>\n <span>{{Data.EntityName}}</span>\n @if (RecordDisplayName) {\n <span class=\"micro-record-name\">{{RecordDisplayName}}</span>\n }\n </div>\n <div class=\"micro-record-id\">\n <i class=\"fa-solid fa-fingerprint\"></i>\n <span>{{DisplayRecordID}}</span>\n </div>\n </div>\n <div class=\"micro-header-actions\">\n <button class=\"micro-open-btn\" (click)=\"OnOpenRecord()\" title=\"Open this record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open\n </button>\n <button class=\"micro-close\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n </div>\n }\n\n <!-- Inline header -->\n @if (Inline) {\n <div class=\"micro-inline-header\">\n <div class=\"micro-header-left\">\n <div class=\"micro-entity\">\n <i [class]=\"EntityIcon\" class=\"micro-entity-icon\"></i>\n <span>{{Data.EntityName}}</span>\n @if (RecordDisplayName) {\n <span class=\"micro-record-name\">{{RecordDisplayName}}</span>\n }\n </div>\n <div class=\"micro-record-id\">\n <i class=\"fa-solid fa-fingerprint\"></i>\n <span>{{DisplayRecordID}}</span>\n </div>\n </div>\n <button class=\"micro-open-btn\" (click)=\"OnOpenRecord()\" title=\"Open this record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open\n </button>\n </div>\n }\n\n <!-- Content -->\n <div class=\"micro-content\" [class.micro-content-inline]=\"Inline\">\n @if (IsLoading) {\n <mj-loading text=\"Loading record data...\"></mj-loading>\n }\n\n <!-- Error -->\n @if (!IsLoading && ErrorMessage) {\n <div class=\"micro-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ErrorMessage}}</span>\n </div>\n }\n\n <!-- Field table -->\n @if (!IsLoading && !ErrorMessage && Fields.length > 0) {\n <div class=\"micro-fields\">\n <!-- Null toggle toolbar -->\n @if (HiddenNullCount > 0) {\n <div class=\"micro-toolbar\">\n <label class=\"null-toggle\">\n <input type=\"checkbox\" [checked]=\"ShowNullValues\" (change)=\"ToggleShowNulls()\" />\n <span class=\"null-toggle-label\">Show null values ({{HiddenNullCount}})</span>\n </label>\n </div>\n }\n <div class=\"micro-field-header\">\n <span class=\"mf-col-name\">Field</span>\n @if (!HasDiffs) {\n <span class=\"mf-col-value\">Value</span>\n }\n @if (HasDiffs) {\n <span class=\"mf-col-old\">Old</span>\n <span class=\"mf-col-new\">New</span>\n }\n </div>\n @for (field of VisibleFields; track field; let odd = $odd) {\n <div class=\"micro-field-row\"\n [class.odd]=\"odd\" [ngClass]=\"field.DiffClass\">\n <span class=\"mf-col-name\" [title]=\"field.Description\">\n <i [class]=\"GetTypeIcon(field.Type)\" class=\"mf-type-icon\"></i>\n <span class=\"mf-field-name\">{{field.DisplayName}}</span>\n </span>\n @if (!HasDiffs) {\n <span class=\"mf-col-value\" [title]=\"field.Value\">\n <!-- Boolean field -->\n @if (field.IsBoolean && !field.IsNull) {\n <i [class]=\"field.BooleanValue ? 'fa-solid fa-square-check mf-bool-true' : 'fa-regular fa-square mf-bool-false'\"\n class=\"mf-bool-icon\"></i>\n <span class=\"mf-bool-label\">{{field.BooleanValue ? 'Yes' : 'No'}}</span>\n }\n <!-- FK field with display value \u2014 show display name (ID) with open icon -->\n @if (!field.IsBoolean && field.ForeignKeyEntityName && field.ForeignKeyDisplayValue) {\n <a class=\"mf-fk-link\" (click)=\"OnEntityLinkClicked($event, field)\"\n [title]=\"field.ForeignKeyEntityName + ': ' + field.ForeignKeyRecordId\">\n {{field.ForeignKeyDisplayValue}}\n <span class=\"mf-fk-id\">({{field.ForeignKeyRecordId | slice:0:8}}...)</span>\n <i class=\"fa-solid fa-arrow-up-right-from-square mf-fk-icon\"></i>\n </a>\n }\n <!-- FK field without display value \u2014 show raw ID with open icon -->\n @if (!field.IsBoolean && field.ForeignKeyEntityName && !field.ForeignKeyDisplayValue) {\n <a class=\"mf-fk-link\" (click)=\"OnEntityLinkClicked($event, field)\"\n [title]=\"'Open ' + field.ForeignKeyEntityName\">\n {{field.Value}}\n <i class=\"fa-solid fa-arrow-up-right-from-square mf-fk-icon\"></i>\n </a>\n }\n <!-- JSON field \u2014 formatted -->\n @if (!field.IsBoolean && !field.ForeignKeyEntityName && field.IsJson) {\n <pre class=\"mf-json-value\">{{field.Value}}</pre>\n }\n <!-- Regular value -->\n @if (!field.IsBoolean && !field.ForeignKeyEntityName && !field.IsJson) {\n {{field.Value}}\n }\n </span>\n }\n @if (HasDiffs) {\n <span class=\"mf-col-old\" [title]=\"field.OldValue\">\n {{field.OldValue || field.Value}}\n </span>\n <span class=\"mf-col-new\" [title]=\"field.Value\">\n {{field.Value}}\n </span>\n }\n </div>\n }\n </div>\n }\n\n <!-- Empty -->\n @if (!IsLoading && !ErrorMessage && Fields.length === 0) {\n <div class=\"micro-empty\">\n <p>No field data available.</p>\n </div>\n }\n </div>\n</ng-template>\n", styles: ["/* ================================================================= */\n/* OVERLAY MODE */\n/* ================================================================= */\n\n.micro-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0);\n z-index: 1100;\n transition: background 0.25s ease;\n pointer-events: none;\n}\n\n.micro-backdrop.visible {\n background: rgba(0, 0, 0, 0.15);\n pointer-events: auto;\n}\n\n.micro-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 480px;\n max-width: 90vw;\n height: 100vh;\n background: var(--card-background, #ffffff);\n box-shadow: -6px 0 24px rgba(0, 0, 0, 0.1);\n z-index: 1101;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.micro-panel.visible {\n transform: translateX(0);\n}\n\n/* ================================================================= */\n/* INLINE MODE */\n/* ================================================================= */\n\n.micro-inline {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.micro-inline-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 16px 24px;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n flex-shrink: 0;\n}\n\n.micro-header-left {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.micro-content-inline {\n padding: 0;\n}\n\n/* ================================================================= */\n/* HEADER (overlay mode) */\n/* ================================================================= */\n\n.micro-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n flex-shrink: 0;\n}\n\n.micro-header-info {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n}\n\n.micro-header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.micro-entity {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 15px;\n font-weight: 600;\n color: var(--text-primary, #1f2937);\n}\n\n.micro-entity-icon {\n color: #3b82f6;\n}\n\n/* Record display name shown prominently next to entity name */\n.micro-record-name {\n color: #6366f1;\n font-weight: 700;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.micro-record-id {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--text-tertiary, #9ca3af);\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.micro-record-id i {\n font-size: 11px;\n}\n\n/* Open record button */\n.micro-open-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 6px 12px;\n background: var(--card-background, #ffffff);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 6px;\n color: #3b82f6;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.micro-open-btn:hover {\n background: #3b82f6;\n color: white;\n border-color: #3b82f6;\n}\n\n.micro-open-btn i {\n font-size: 11px;\n}\n\n.micro-close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: none;\n border: none;\n border-radius: 6px;\n color: var(--text-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.micro-close:hover {\n background: var(--hover-background, #f3f4f6);\n color: var(--text-primary, #1f2937);\n}\n\n/* ================================================================= */\n/* CONTENT */\n/* ================================================================= */\n\n.micro-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.micro-error {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 20px;\n margin: 0 20px;\n background: rgba(239, 68, 68, 0.06);\n border: 1px solid rgba(239, 68, 68, 0.15);\n border-radius: 8px;\n font-size: 13px;\n color: #ef4444;\n}\n\n/* Null toggle toolbar */\n.micro-toolbar {\n display: flex;\n align-items: center;\n padding: 8px 20px;\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n}\n\n.null-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n user-select: none;\n}\n\n.null-toggle input[type=\"checkbox\"] {\n width: 14px;\n height: 14px;\n accent-color: #6366f1;\n cursor: pointer;\n}\n\n.null-toggle-label {\n font-weight: 500;\n}\n\n/* Field table */\n.micro-fields {\n font-size: 13px;\n}\n\n.micro-field-header {\n display: grid;\n grid-template-columns: 180px 1fr;\n padding: 8px 20px;\n font-size: 11px;\n font-weight: 600;\n color: var(--text-tertiary, #9ca3af);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n position: sticky;\n top: 0;\n background: var(--card-background, #ffffff);\n z-index: 1;\n}\n\n.micro-field-header:has(.mf-col-old) {\n grid-template-columns: 160px 1fr 1fr;\n}\n\n.micro-field-row {\n display: grid;\n grid-template-columns: 180px 1fr;\n padding: 7px 20px;\n align-items: baseline;\n border-bottom: 1px solid var(--border-color, #f3f4f6);\n transition: background 0.1s ease;\n}\n\n.micro-field-row:hover {\n background: var(--hover-background, #f9fafb);\n}\n\n.micro-field-row.odd {\n background: var(--hover-background, #fafafa);\n}\n\n.micro-field-row.odd:hover {\n background: #f3f4f6;\n}\n\n/* Diff styling */\n.micro-field-row.diff-added {\n background: rgba(16, 185, 129, 0.04) !important;\n border-left: 3px solid #10b981;\n}\n\n.micro-field-row.diff-modified {\n background: rgba(245, 158, 11, 0.04) !important;\n border-left: 3px solid #f59e0b;\n}\n\n.micro-field-row.diff-removed {\n background: rgba(239, 68, 68, 0.04) !important;\n border-left: 3px solid #ef4444;\n}\n\n.micro-field-row:has(.mf-col-old) {\n grid-template-columns: 160px 1fr 1fr;\n}\n\n.mf-col-name {\n display: flex;\n align-items: center;\n gap: 6px;\n overflow: hidden;\n cursor: default;\n}\n\n.mf-type-icon {\n color: var(--text-tertiary, #d1d5db);\n font-size: 11px;\n width: 14px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.mf-field-name {\n font-weight: 500;\n color: var(--text-primary, #1f2937);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mf-col-value,\n.mf-col-old,\n.mf-col-new {\n color: var(--text-secondary, #6b7280);\n word-break: break-word;\n line-height: 1.4;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 12px;\n}\n\n.mf-col-old {\n color: #ef4444;\n opacity: 0.7;\n text-decoration: line-through;\n}\n\n.mf-col-new {\n color: #10b981;\n}\n\n/* ================================================================= */\n/* BOOLEAN FIELD DISPLAY */\n/* ================================================================= */\n\n.mf-bool-icon {\n font-size: 14px;\n vertical-align: middle;\n}\n\n.mf-bool-true {\n color: #10b981;\n}\n\n.mf-bool-false {\n color: var(--text-tertiary, #d1d5db);\n}\n\n.mf-bool-label {\n margin-left: 6px;\n font-family: inherit;\n font-size: 12px;\n color: var(--text-secondary, #6b7280);\n}\n\n/* ================================================================= */\n/* FOREIGN KEY LINK STYLES */\n/* ================================================================= */\n\n.mf-fk-link {\n color: #3b82f6;\n cursor: pointer;\n text-decoration: none;\n font-family: inherit;\n font-size: inherit;\n transition: color 0.15s ease;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.mf-fk-link:hover {\n color: #2563eb;\n text-decoration: underline;\n}\n\n.mf-fk-id {\n color: var(--text-tertiary, #9ca3af);\n font-size: 10px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n}\n\n.mf-fk-icon {\n font-size: 9px;\n opacity: 0.6;\n transition: opacity 0.15s ease;\n}\n\n.mf-fk-link:hover .mf-fk-icon {\n opacity: 1;\n}\n\n/* ================================================================= */\n/* JSON FIELD DISPLAY */\n/* ================================================================= */\n\n.mf-json-value {\n margin: 0;\n padding: 8px 10px;\n background: var(--hover-background, #f9fafb);\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 6px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 11px;\n line-height: 1.5;\n color: var(--text-secondary, #6b7280);\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n/* Empty */\n.micro-empty {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.micro-empty p {\n font-size: 14px;\n color: var(--text-tertiary, #9ca3af);\n margin: 0;\n}\n\n/* ================================================================= */\n/* INLINE MODE - Responsive */\n/* ================================================================= */\n\n.micro-inline .micro-field-header,\n.micro-inline .micro-field-row {\n padding-left: 24px;\n padding-right: 24px;\n}\n\n.micro-inline .micro-toolbar {\n padding-left: 24px;\n padding-right: 24px;\n}\n\n@media (max-width: 600px) {\n .micro-field-header,\n .micro-field-row {\n grid-template-columns: 120px 1fr;\n }\n\n .micro-field-header:has(.mf-col-old),\n .micro-field-row:has(.mf-col-old) {\n grid-template-columns: 100px 1fr 1fr;\n }\n\n .micro-record-name {\n max-width: 120px;\n }\n}\n"] }]
|
|
809
|
+
}], () => [{ type: i0.ChangeDetectorRef }], { Data: [{
|
|
810
|
+
type: Input
|
|
811
|
+
}], Inline: [{
|
|
812
|
+
type: Input
|
|
813
|
+
}], Close: [{
|
|
814
|
+
type: Output
|
|
815
|
+
}], EntityLinkClick: [{
|
|
816
|
+
type: Output
|
|
817
|
+
}], OpenRecord: [{
|
|
818
|
+
type: Output
|
|
819
|
+
}], OnEscapeKey: [{
|
|
820
|
+
type: HostListener,
|
|
821
|
+
args: ['document:keydown.escape']
|
|
822
|
+
}] }); })();
|
|
823
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MjRecordMicroViewComponent, { className: "MjRecordMicroViewComponent", filePath: "src/lib/record-micro-view/record-micro-view.component.ts", lineNumber: 44 }); })();
|
|
824
|
+
//# sourceMappingURL=record-micro-view.component.js.map
|