@memberjunction/ng-entity-viewer 5.14.0 → 5.15.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/entity-record-detail-panel/entity-record-detail-panel.component.d.ts +51 -2
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts.map +1 -1
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js +364 -10
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js.map +1 -1
- package/package.json +10 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter, OnChanges, SimpleChanges, ChangeDetectorRef, NgZone } from '@angular/core';
|
|
2
|
-
import { EntityInfo, EntityRelationshipInfo } from '@memberjunction/core';
|
|
2
|
+
import { EntityInfo, EntityRelationshipInfo, EntityOrganicKeyInfo, EntityOrganicKeyRelatedEntityInfo } from '@memberjunction/core';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
interface RelatedEntityData {
|
|
5
5
|
relationship: EntityRelationshipInfo;
|
|
@@ -9,6 +9,15 @@ interface RelatedEntityData {
|
|
|
9
9
|
records: Record<string, unknown>[];
|
|
10
10
|
isLoadingRecords: boolean;
|
|
11
11
|
}
|
|
12
|
+
interface OrganicKeyMatchData {
|
|
13
|
+
organicKey: EntityOrganicKeyInfo;
|
|
14
|
+
relatedEntity: EntityOrganicKeyRelatedEntityInfo;
|
|
15
|
+
relatedEntityName: string;
|
|
16
|
+
count: number;
|
|
17
|
+
isExpanded: boolean;
|
|
18
|
+
records: Record<string, unknown>[];
|
|
19
|
+
isLoadingRecords: boolean;
|
|
20
|
+
}
|
|
12
21
|
/**
|
|
13
22
|
* Field display types for categorizing how to render each field
|
|
14
23
|
*/
|
|
@@ -79,15 +88,55 @@ export declare class EntityRecordDetailPanelComponent implements OnChanges {
|
|
|
79
88
|
openForeignKeyRecord: EventEmitter<OpenForeignKeyRecordEvent>;
|
|
80
89
|
relatedEntities: RelatedEntityData[];
|
|
81
90
|
isLoadingRelationships: boolean;
|
|
91
|
+
organicKeyMatches: OrganicKeyMatchData[];
|
|
92
|
+
isLoadingOrganicKeys: boolean;
|
|
82
93
|
private metadata;
|
|
83
94
|
detailsSectionExpanded: boolean;
|
|
84
95
|
relationshipsSectionExpanded: boolean;
|
|
96
|
+
organicKeysSectionExpanded: boolean;
|
|
85
97
|
constructor(cdr: ChangeDetectorRef, ngZone: NgZone);
|
|
86
98
|
ngOnChanges(changes: SimpleChanges): void;
|
|
87
99
|
/**
|
|
88
100
|
* Load counts for related entities using batch RunViews call
|
|
89
101
|
*/
|
|
90
102
|
private loadRelationshipCounts;
|
|
103
|
+
/**
|
|
104
|
+
* Load counts for organic key matches using batch RunViews call.
|
|
105
|
+
* Builds query filters using EntityInfo.BuildOrganicKeyViewParams for each related entity.
|
|
106
|
+
*/
|
|
107
|
+
private loadOrganicKeyCounts;
|
|
108
|
+
/**
|
|
109
|
+
* Get only organic key matches that have records (count > 0)
|
|
110
|
+
*/
|
|
111
|
+
get organicKeyMatchesWithRecords(): OrganicKeyMatchData[];
|
|
112
|
+
/**
|
|
113
|
+
* Toggle expansion of an organic key match section and load records if needed
|
|
114
|
+
*/
|
|
115
|
+
toggleOrganicKeyExpansion(match: OrganicKeyMatchData, event: Event): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Load actual records for an organic key match
|
|
118
|
+
*/
|
|
119
|
+
private loadOrganicKeyRecords;
|
|
120
|
+
/**
|
|
121
|
+
* Handle click on an organic key record
|
|
122
|
+
*/
|
|
123
|
+
onOrganicKeyRecordClick(match: OrganicKeyMatchData, record: Record<string, unknown>, event: Event): void;
|
|
124
|
+
/**
|
|
125
|
+
* Navigate to view all organic key matched records
|
|
126
|
+
*/
|
|
127
|
+
onViewAllOrganicKey(match: OrganicKeyMatchData, event: Event): void;
|
|
128
|
+
/**
|
|
129
|
+
* Get display name for an organic key record
|
|
130
|
+
*/
|
|
131
|
+
getOrganicKeyRecordDisplayName(match: OrganicKeyMatchData, record: Record<string, unknown>): string;
|
|
132
|
+
/**
|
|
133
|
+
* Get subtitle for an organic key record
|
|
134
|
+
*/
|
|
135
|
+
getOrganicKeyRecordSubtitle(match: OrganicKeyMatchData, record: Record<string, unknown>): string;
|
|
136
|
+
/**
|
|
137
|
+
* Get icon for an organic key matched entity
|
|
138
|
+
*/
|
|
139
|
+
getOrganicKeyEntityIcon(match: OrganicKeyMatchData): string;
|
|
91
140
|
/**
|
|
92
141
|
* Get key fields to display in details section, categorized by type
|
|
93
142
|
*/
|
|
@@ -158,7 +207,7 @@ export declare class EntityRecordDetailPanelComponent implements OnChanges {
|
|
|
158
207
|
/**
|
|
159
208
|
* Toggle section expansion
|
|
160
209
|
*/
|
|
161
|
-
toggleSection(section: 'details' | 'relationships'): void;
|
|
210
|
+
toggleSection(section: 'details' | 'relationships' | 'organicKeys'): void;
|
|
162
211
|
/**
|
|
163
212
|
* Get only related entities that have records (count > 0)
|
|
164
213
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-record-detail-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/entity-record-detail-panel/entity-record-detail-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5H,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAA6F,MAAM,sBAAsB,CAAC;;
|
|
1
|
+
{"version":3,"file":"entity-record-detail-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/entity-record-detail-panel/entity-record-detail-panel.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
-
import { RunView, Metadata, EntityFieldValueListType } from '@memberjunction/core';
|
|
2
|
+
import { EntityInfo, RunView, Metadata, EntityFieldValueListType } from '@memberjunction/core';
|
|
3
3
|
import { buildCompositeKey, buildPkString } from '../utils/record.util';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
import * as i1 from "@memberjunction/ng-shared-generic";
|
|
@@ -247,6 +247,146 @@ function EntityRecordDetailPanelComponent_Conditional_22_Template(rf, ctx) { if
|
|
|
247
247
|
i0.ɵɵadvance();
|
|
248
248
|
i0.ɵɵconditional(ctx_r0.isLoadingRelationships ? 1 : ctx_r0.relatedEntitiesWithRecords.length === 0 ? 2 : 3);
|
|
249
249
|
} }
|
|
250
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
251
|
+
i0.ɵɵelementStart(0, "div", 35);
|
|
252
|
+
i0.ɵɵelement(1, "mj-loading", 56);
|
|
253
|
+
i0.ɵɵelementEnd();
|
|
254
|
+
} }
|
|
255
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
256
|
+
i0.ɵɵelementStart(0, "div", 19);
|
|
257
|
+
i0.ɵɵtext(1, "No organic key matches");
|
|
258
|
+
i0.ɵɵelementEnd();
|
|
259
|
+
} }
|
|
260
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
261
|
+
i0.ɵɵelementStart(0, "div", 44);
|
|
262
|
+
i0.ɵɵelement(1, "mj-loading", 45);
|
|
263
|
+
i0.ɵɵelementEnd();
|
|
264
|
+
} }
|
|
265
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_For_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
266
|
+
i0.ɵɵelementStart(0, "span", 51);
|
|
267
|
+
i0.ɵɵtext(1);
|
|
268
|
+
i0.ɵɵelementEnd();
|
|
269
|
+
} if (rf & 2) {
|
|
270
|
+
i0.ɵɵadvance();
|
|
271
|
+
i0.ɵɵtextInterpolate(ctx);
|
|
272
|
+
} }
|
|
273
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
274
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
275
|
+
i0.ɵɵelementStart(0, "div", 48);
|
|
276
|
+
i0.ɵɵlistener("click", function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_For_1_Template_div_click_0_listener($event) { const rec_r14 = i0.ɵɵrestoreView(_r13).$implicit; const match_r12 = i0.ɵɵnextContext(3).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.onOrganicKeyRecordClick(match_r12, rec_r14, $event)); });
|
|
277
|
+
i0.ɵɵelementStart(1, "div", 49)(2, "span", 50);
|
|
278
|
+
i0.ɵɵtext(3);
|
|
279
|
+
i0.ɵɵelementEnd();
|
|
280
|
+
i0.ɵɵconditionalCreate(4, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_For_1_Conditional_4_Template, 2, 1, "span", 51);
|
|
281
|
+
i0.ɵɵelementEnd();
|
|
282
|
+
i0.ɵɵelement(5, "i", 52);
|
|
283
|
+
i0.ɵɵelementEnd();
|
|
284
|
+
} if (rf & 2) {
|
|
285
|
+
let tmp_26_0;
|
|
286
|
+
const rec_r14 = ctx.$implicit;
|
|
287
|
+
const match_r12 = i0.ɵɵnextContext(3).$implicit;
|
|
288
|
+
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
289
|
+
i0.ɵɵadvance(3);
|
|
290
|
+
i0.ɵɵtextInterpolate(ctx_r0.getOrganicKeyRecordDisplayName(match_r12, rec_r14));
|
|
291
|
+
i0.ɵɵadvance();
|
|
292
|
+
i0.ɵɵconditional((tmp_26_0 = ctx_r0.getOrganicKeyRecordSubtitle(match_r12, rec_r14)) ? 4 : -1, tmp_26_0);
|
|
293
|
+
} }
|
|
294
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
295
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
296
|
+
i0.ɵɵelementStart(0, "div", 53);
|
|
297
|
+
i0.ɵɵlistener("click", function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_Conditional_2_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r15); const match_r12 = i0.ɵɵnextContext(3).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.onViewAllOrganicKey(match_r12, $event)); });
|
|
298
|
+
i0.ɵɵelementStart(1, "span");
|
|
299
|
+
i0.ɵɵtext(2);
|
|
300
|
+
i0.ɵɵelementEnd();
|
|
301
|
+
i0.ɵɵelement(3, "i", 54);
|
|
302
|
+
i0.ɵɵelementEnd();
|
|
303
|
+
} if (rf & 2) {
|
|
304
|
+
const match_r12 = i0.ɵɵnextContext(3).$implicit;
|
|
305
|
+
i0.ɵɵadvance(2);
|
|
306
|
+
i0.ɵɵtextInterpolate1("View all ", match_r12.count, " records");
|
|
307
|
+
} }
|
|
308
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
309
|
+
i0.ɵɵrepeaterCreate(0, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_For_1_Template, 6, 2, "div", 46, i0.ɵɵrepeaterTrackByIndex);
|
|
310
|
+
i0.ɵɵconditionalCreate(2, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_Conditional_2_Template, 4, 1, "div", 47);
|
|
311
|
+
} if (rf & 2) {
|
|
312
|
+
const match_r12 = i0.ɵɵnextContext(2).$implicit;
|
|
313
|
+
i0.ɵɵrepeater(match_r12.records);
|
|
314
|
+
i0.ɵɵadvance(2);
|
|
315
|
+
i0.ɵɵconditional(match_r12.count > 10 ? 2 : -1);
|
|
316
|
+
} }
|
|
317
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
318
|
+
i0.ɵɵelementStart(0, "div", 43);
|
|
319
|
+
i0.ɵɵconditionalCreate(1, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_1_Template, 2, 0, "div", 44)(2, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Conditional_2_Template, 3, 1);
|
|
320
|
+
i0.ɵɵelementEnd();
|
|
321
|
+
} if (rf & 2) {
|
|
322
|
+
const match_r12 = i0.ɵɵnextContext().$implicit;
|
|
323
|
+
i0.ɵɵadvance();
|
|
324
|
+
i0.ɵɵconditional(match_r12.isLoadingRecords ? 1 : 2);
|
|
325
|
+
} }
|
|
326
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
327
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
328
|
+
i0.ɵɵelementStart(0, "div", 38)(1, "div", 39);
|
|
329
|
+
i0.ɵɵlistener("click", function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Template_div_click_1_listener($event) { const match_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleOrganicKeyExpansion(match_r12, $event)); });
|
|
330
|
+
i0.ɵɵelement(2, "i", 40)(3, "i");
|
|
331
|
+
i0.ɵɵelementStart(4, "span", 41);
|
|
332
|
+
i0.ɵɵtext(5);
|
|
333
|
+
i0.ɵɵelementEnd();
|
|
334
|
+
i0.ɵɵelementStart(6, "span", 42);
|
|
335
|
+
i0.ɵɵtext(7);
|
|
336
|
+
i0.ɵɵelementEnd()();
|
|
337
|
+
i0.ɵɵconditionalCreate(8, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Conditional_8_Template, 3, 1, "div", 43);
|
|
338
|
+
i0.ɵɵelementEnd();
|
|
339
|
+
} if (rf & 2) {
|
|
340
|
+
const match_r12 = ctx.$implicit;
|
|
341
|
+
const ctx_r0 = i0.ɵɵnextContext(4);
|
|
342
|
+
i0.ɵɵclassProp("expanded", match_r12.isExpanded);
|
|
343
|
+
i0.ɵɵadvance();
|
|
344
|
+
i0.ɵɵclassProp("clickable", match_r12.count > 0);
|
|
345
|
+
i0.ɵɵadvance();
|
|
346
|
+
i0.ɵɵclassProp("fa-chevron-down", match_r12.isExpanded)("fa-chevron-right", !match_r12.isExpanded);
|
|
347
|
+
i0.ɵɵadvance();
|
|
348
|
+
i0.ɵɵclassMap(ctx_r0.getOrganicKeyEntityIcon(match_r12));
|
|
349
|
+
i0.ɵɵadvance(2);
|
|
350
|
+
i0.ɵɵtextInterpolate(match_r12.relatedEntityName);
|
|
351
|
+
i0.ɵɵadvance(2);
|
|
352
|
+
i0.ɵɵtextInterpolate(match_r12.count);
|
|
353
|
+
i0.ɵɵadvance();
|
|
354
|
+
i0.ɵɵconditional(match_r12.isExpanded ? 8 : -1);
|
|
355
|
+
} }
|
|
356
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
357
|
+
i0.ɵɵrepeaterCreate(0, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_For_1_Template, 9, 13, "div", 37, _forTrack1);
|
|
358
|
+
} if (rf & 2) {
|
|
359
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
360
|
+
i0.ɵɵrepeater(ctx_r0.organicKeyMatchesWithRecords);
|
|
361
|
+
} }
|
|
362
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
363
|
+
i0.ɵɵelementStart(0, "div", 13);
|
|
364
|
+
i0.ɵɵconditionalCreate(1, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_1_Template, 2, 0, "div", 35)(2, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_2_Template, 2, 0, "div", 19)(3, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Conditional_3_Template, 2, 0);
|
|
365
|
+
i0.ɵɵelementEnd();
|
|
366
|
+
} if (rf & 2) {
|
|
367
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
368
|
+
i0.ɵɵadvance();
|
|
369
|
+
i0.ɵɵconditional(ctx_r0.isLoadingOrganicKeys ? 1 : ctx_r0.organicKeyMatchesWithRecords.length === 0 ? 2 : 3);
|
|
370
|
+
} }
|
|
371
|
+
function EntityRecordDetailPanelComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
372
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
373
|
+
i0.ɵɵelementStart(0, "div", 8)(1, "div", 9);
|
|
374
|
+
i0.ɵɵlistener("click", function EntityRecordDetailPanelComponent_Conditional_23_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleSection("organicKeys")); });
|
|
375
|
+
i0.ɵɵelement(2, "i", 55);
|
|
376
|
+
i0.ɵɵelementStart(3, "span", 11);
|
|
377
|
+
i0.ɵɵtext(4, "Organic Key Matches");
|
|
378
|
+
i0.ɵɵelementEnd();
|
|
379
|
+
i0.ɵɵelement(5, "i", 12);
|
|
380
|
+
i0.ɵɵelementEnd();
|
|
381
|
+
i0.ɵɵconditionalCreate(6, EntityRecordDetailPanelComponent_Conditional_23_Conditional_6_Template, 4, 1, "div", 13);
|
|
382
|
+
i0.ɵɵelementEnd();
|
|
383
|
+
} if (rf & 2) {
|
|
384
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
385
|
+
i0.ɵɵadvance(5);
|
|
386
|
+
i0.ɵɵclassProp("fa-chevron-down", ctx_r0.organicKeysSectionExpanded)("fa-chevron-right", !ctx_r0.organicKeysSectionExpanded);
|
|
387
|
+
i0.ɵɵadvance();
|
|
388
|
+
i0.ɵɵconditional(ctx_r0.organicKeysSectionExpanded ? 6 : -1);
|
|
389
|
+
} }
|
|
250
390
|
/**
|
|
251
391
|
* EntityRecordDetailPanelComponent - A reusable panel for displaying entity record details
|
|
252
392
|
*
|
|
@@ -281,10 +421,14 @@ export class EntityRecordDetailPanelComponent {
|
|
|
281
421
|
// Related entity counts
|
|
282
422
|
relatedEntities = [];
|
|
283
423
|
isLoadingRelationships = false;
|
|
424
|
+
// Organic key match counts
|
|
425
|
+
organicKeyMatches = [];
|
|
426
|
+
isLoadingOrganicKeys = false;
|
|
284
427
|
metadata = new Metadata();
|
|
285
428
|
// Sections expanded state
|
|
286
429
|
detailsSectionExpanded = true;
|
|
287
430
|
relationshipsSectionExpanded = true;
|
|
431
|
+
organicKeysSectionExpanded = true;
|
|
288
432
|
constructor(cdr, ngZone) {
|
|
289
433
|
this.cdr = cdr;
|
|
290
434
|
this.ngZone = ngZone;
|
|
@@ -292,6 +436,7 @@ export class EntityRecordDetailPanelComponent {
|
|
|
292
436
|
ngOnChanges(changes) {
|
|
293
437
|
if (changes['record'] && this.record && this.entity) {
|
|
294
438
|
this.loadRelationshipCounts();
|
|
439
|
+
this.loadOrganicKeyCounts();
|
|
295
440
|
}
|
|
296
441
|
}
|
|
297
442
|
/**
|
|
@@ -357,6 +502,208 @@ export class EntityRecordDetailPanelComponent {
|
|
|
357
502
|
});
|
|
358
503
|
}
|
|
359
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* Load counts for organic key matches using batch RunViews call.
|
|
507
|
+
* Builds query filters using EntityInfo.BuildOrganicKeyViewParams for each related entity.
|
|
508
|
+
*/
|
|
509
|
+
async loadOrganicKeyCounts() {
|
|
510
|
+
if (!this.entity || !this.record)
|
|
511
|
+
return;
|
|
512
|
+
const organicKeys = this.entity.OrganicKeys;
|
|
513
|
+
if (!organicKeys || organicKeys.length === 0) {
|
|
514
|
+
this.organicKeyMatches = [];
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
// Flatten all organic key related entities
|
|
518
|
+
const allPairs = [];
|
|
519
|
+
for (const ok of organicKeys) {
|
|
520
|
+
for (const re of ok.RelatedEntities) {
|
|
521
|
+
allPairs.push({ organicKey: ok, relatedEntity: re });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (allPairs.length === 0) {
|
|
525
|
+
this.organicKeyMatches = [];
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
this.isLoadingOrganicKeys = true;
|
|
529
|
+
this.organicKeyMatches = [];
|
|
530
|
+
// Build a mock BaseEntity-like object for BuildOrganicKeyViewParams
|
|
531
|
+
// The static method only calls record.Get(fieldName), so we can duck-type it
|
|
532
|
+
const mockRecord = {
|
|
533
|
+
Get: (fieldName) => this.record ? this.record[fieldName] ?? null : null,
|
|
534
|
+
EntityInfo: this.entity,
|
|
535
|
+
};
|
|
536
|
+
// Build batch query params
|
|
537
|
+
const viewParams = allPairs.map(pair => {
|
|
538
|
+
const params = EntityInfo.BuildOrganicKeyViewParams(mockRecord, pair.relatedEntity, pair.organicKey);
|
|
539
|
+
params.ResultType = 'count_only';
|
|
540
|
+
return params;
|
|
541
|
+
});
|
|
542
|
+
try {
|
|
543
|
+
const rv = new RunView();
|
|
544
|
+
const results = await rv.RunViews(viewParams);
|
|
545
|
+
this.organicKeyMatches = allPairs.map((pair, index) => {
|
|
546
|
+
const result = results[index];
|
|
547
|
+
return {
|
|
548
|
+
organicKey: pair.organicKey,
|
|
549
|
+
relatedEntity: pair.relatedEntity,
|
|
550
|
+
relatedEntityName: pair.relatedEntity.DisplayName || pair.relatedEntity.RelatedEntity,
|
|
551
|
+
count: result.Success ? result.TotalRowCount : 0,
|
|
552
|
+
isExpanded: false,
|
|
553
|
+
records: [],
|
|
554
|
+
isLoadingRecords: false,
|
|
555
|
+
};
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
console.warn('Failed to load organic key counts:', error);
|
|
560
|
+
this.organicKeyMatches = allPairs.map(pair => ({
|
|
561
|
+
organicKey: pair.organicKey,
|
|
562
|
+
relatedEntity: pair.relatedEntity,
|
|
563
|
+
relatedEntityName: pair.relatedEntity.DisplayName || pair.relatedEntity.RelatedEntity,
|
|
564
|
+
count: 0,
|
|
565
|
+
isExpanded: false,
|
|
566
|
+
records: [],
|
|
567
|
+
isLoadingRecords: false,
|
|
568
|
+
}));
|
|
569
|
+
}
|
|
570
|
+
finally {
|
|
571
|
+
this.ngZone.run(() => {
|
|
572
|
+
this.isLoadingOrganicKeys = false;
|
|
573
|
+
this.cdr.detectChanges();
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Get only organic key matches that have records (count > 0)
|
|
579
|
+
*/
|
|
580
|
+
get organicKeyMatchesWithRecords() {
|
|
581
|
+
return this.organicKeyMatches.filter(m => m.count > 0);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Toggle expansion of an organic key match section and load records if needed
|
|
585
|
+
*/
|
|
586
|
+
async toggleOrganicKeyExpansion(match, event) {
|
|
587
|
+
event.stopPropagation();
|
|
588
|
+
if (match.count === 0)
|
|
589
|
+
return;
|
|
590
|
+
match.isExpanded = !match.isExpanded;
|
|
591
|
+
if (match.isExpanded && match.records.length === 0 && !match.isLoadingRecords) {
|
|
592
|
+
await this.loadOrganicKeyRecords(match);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Load actual records for an organic key match
|
|
597
|
+
*/
|
|
598
|
+
async loadOrganicKeyRecords(match) {
|
|
599
|
+
if (!this.record || !this.entity)
|
|
600
|
+
return;
|
|
601
|
+
match.isLoadingRecords = true;
|
|
602
|
+
this.cdr.detectChanges();
|
|
603
|
+
const mockRecord = {
|
|
604
|
+
Get: (fieldName) => this.record ? this.record[fieldName] ?? null : null,
|
|
605
|
+
EntityInfo: this.entity,
|
|
606
|
+
};
|
|
607
|
+
try {
|
|
608
|
+
const params = EntityInfo.BuildOrganicKeyViewParams(mockRecord, match.relatedEntity, match.organicKey);
|
|
609
|
+
const rv = new RunView();
|
|
610
|
+
const relatedEntityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);
|
|
611
|
+
const fields = relatedEntityInfo
|
|
612
|
+
? [...relatedEntityInfo.PrimaryKeys.map(pk => pk.Name),
|
|
613
|
+
...(relatedEntityInfo.NameField ? [relatedEntityInfo.NameField.Name] : []),
|
|
614
|
+
...relatedEntityInfo.Fields.filter(f => f.DefaultInView).map(f => f.Name)]
|
|
615
|
+
: undefined;
|
|
616
|
+
const result = await rv.RunView({
|
|
617
|
+
...params,
|
|
618
|
+
ResultType: 'simple',
|
|
619
|
+
...(fields ? { Fields: fields } : {}),
|
|
620
|
+
MaxRows: 10,
|
|
621
|
+
});
|
|
622
|
+
if (result.Success) {
|
|
623
|
+
match.records = result.Results;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
catch (error) {
|
|
627
|
+
console.warn(`Failed to load organic key records for ${match.relatedEntityName}:`, error);
|
|
628
|
+
}
|
|
629
|
+
finally {
|
|
630
|
+
this.ngZone.run(() => {
|
|
631
|
+
match.isLoadingRecords = false;
|
|
632
|
+
this.cdr.detectChanges();
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Handle click on an organic key record
|
|
638
|
+
*/
|
|
639
|
+
onOrganicKeyRecordClick(match, record, event) {
|
|
640
|
+
event.stopPropagation();
|
|
641
|
+
this.openRelatedRecord.emit({
|
|
642
|
+
entityName: match.relatedEntity.RelatedEntity,
|
|
643
|
+
record,
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Navigate to view all organic key matched records
|
|
648
|
+
*/
|
|
649
|
+
onViewAllOrganicKey(match, event) {
|
|
650
|
+
event.stopPropagation();
|
|
651
|
+
if (!this.record || !this.entity)
|
|
652
|
+
return;
|
|
653
|
+
const mockRecord = {
|
|
654
|
+
Get: (fieldName) => this.record ? this.record[fieldName] ?? null : null,
|
|
655
|
+
EntityInfo: this.entity,
|
|
656
|
+
};
|
|
657
|
+
const params = EntityInfo.BuildOrganicKeyViewParams(mockRecord, match.relatedEntity, match.organicKey);
|
|
658
|
+
this.navigateToRelated.emit({
|
|
659
|
+
entityName: match.relatedEntity.RelatedEntity,
|
|
660
|
+
filter: String(params.ExtraFilter || ''),
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Get display name for an organic key record
|
|
665
|
+
*/
|
|
666
|
+
getOrganicKeyRecordDisplayName(match, record) {
|
|
667
|
+
const entityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);
|
|
668
|
+
if (entityInfo?.NameField) {
|
|
669
|
+
const name = record[entityInfo.NameField.Name];
|
|
670
|
+
if (name)
|
|
671
|
+
return String(name);
|
|
672
|
+
}
|
|
673
|
+
if (entityInfo) {
|
|
674
|
+
return buildPkString(record, entityInfo);
|
|
675
|
+
}
|
|
676
|
+
return 'Record';
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Get subtitle for an organic key record
|
|
680
|
+
*/
|
|
681
|
+
getOrganicKeyRecordSubtitle(match, record) {
|
|
682
|
+
const entityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);
|
|
683
|
+
if (!entityInfo)
|
|
684
|
+
return '';
|
|
685
|
+
const subtitleFieldNames = ['Description', 'Status', 'Type', 'Email', 'Date', 'Amount', 'Total'];
|
|
686
|
+
for (const fieldName of subtitleFieldNames) {
|
|
687
|
+
const field = entityInfo.Fields.find(f => f.Name.includes(fieldName) && f.Name !== entityInfo.NameField?.Name);
|
|
688
|
+
if (field) {
|
|
689
|
+
const value = record[field.Name];
|
|
690
|
+
if (value !== null && value !== undefined) {
|
|
691
|
+
return this.formatFieldValue(value, field.Name);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return '';
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Get icon for an organic key matched entity
|
|
699
|
+
*/
|
|
700
|
+
getOrganicKeyEntityIcon(match) {
|
|
701
|
+
const entityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);
|
|
702
|
+
if (entityInfo?.Icon) {
|
|
703
|
+
return this.formatEntityIcon(entityInfo.Icon);
|
|
704
|
+
}
|
|
705
|
+
return 'fa-solid fa-link';
|
|
706
|
+
}
|
|
360
707
|
/**
|
|
361
708
|
* Get key fields to display in details section, categorized by type
|
|
362
709
|
*/
|
|
@@ -682,9 +1029,12 @@ export class EntityRecordDetailPanelComponent {
|
|
|
682
1029
|
if (section === 'details') {
|
|
683
1030
|
this.detailsSectionExpanded = !this.detailsSectionExpanded;
|
|
684
1031
|
}
|
|
685
|
-
else {
|
|
1032
|
+
else if (section === 'relationships') {
|
|
686
1033
|
this.relationshipsSectionExpanded = !this.relationshipsSectionExpanded;
|
|
687
1034
|
}
|
|
1035
|
+
else {
|
|
1036
|
+
this.organicKeysSectionExpanded = !this.organicKeysSectionExpanded;
|
|
1037
|
+
}
|
|
688
1038
|
}
|
|
689
1039
|
/**
|
|
690
1040
|
* Get only related entities that have records (count > 0)
|
|
@@ -733,7 +1083,7 @@ export class EntityRecordDetailPanelComponent {
|
|
|
733
1083
|
return `fa-solid fa-${icon}`;
|
|
734
1084
|
}
|
|
735
1085
|
static ɵfac = function EntityRecordDetailPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EntityRecordDetailPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone)); };
|
|
736
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityRecordDetailPanelComponent, selectors: [["mj-entity-record-detail-panel"]], inputs: { entity: "entity", record: "record" }, outputs: { close: "close", openRecord: "openRecord", navigateToRelated: "navigateToRelated", openRelatedRecord: "openRelatedRecord", openForeignKeyRecord: "openForeignKeyRecord" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls:
|
|
1086
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityRecordDetailPanelComponent, selectors: [["mj-entity-record-detail-panel"]], inputs: { entity: "entity", record: "record" }, outputs: { close: "close", openRecord: "openRecord", navigateToRelated: "navigateToRelated", openRelatedRecord: "openRelatedRecord", openForeignKeyRecord: "openForeignKeyRecord" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 28, vars: 13, consts: [[1, "entity-record-card-container"], [1, "panel-header"], [1, "panel-title-row"], [1, "entity-icon", 3, "class"], [1, "panel-title"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "section"], [1, "section-header", 3, "click"], [1, "fa-solid", "fa-info-circle", "section-icon"], [1, "section-title"], [1, "fa-solid", "expand-icon"], [1, "section-content"], [1, "fa-solid", "fa-project-diagram", "section-icon"], [1, "panel-footer"], [1, "open-record-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "entity-icon"], [1, "empty-section"], [1, "field-row", "field-row-pk"], [1, "field-row", "field-row-fk"], [1, "field-row"], [1, "pk-row"], [1, "fa-solid", "fa-key", "pk-icon"], [1, "field-label"], ["title", "Copy ID", 1, "copy-btn", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "fk-value-row"], [1, "field-value", "fk-display-value"], [1, "field-value", "fk-id-value"], [1, "fk-link-btn", 3, "title"], [1, "fk-link-btn", 3, "click", "title"], [3, "value"], [1, "field-value"], [1, "relationships-loading"], ["text", "Loading related records...", "size", "small"], [1, "related-entity-group", 3, "expanded"], [1, "related-entity-group"], [1, "related-entity-header", 3, "click"], [1, "fa-solid", "expand-chevron"], [1, "related-entity-name"], [1, "related-entity-count"], [1, "related-records-list"], [1, "records-loading"], ["text", "Loading...", "size", "small"], [1, "related-record-item"], [1, "view-all-link"], [1, "related-record-item", 3, "click"], [1, "record-info"], [1, "record-name"], [1, "record-subtitle"], [1, "fa-solid", "fa-external-link-alt", "record-open-icon"], [1, "view-all-link", 3, "click"], [1, "fa-solid", "fa-arrow-right"], [1, "fa-solid", "fa-link", "section-icon"], ["text", "Loading organic key matches...", "size", "small"]], template: function EntityRecordDetailPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
737
1087
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
|
|
738
1088
|
i0.ɵɵconditionalCreate(3, EntityRecordDetailPanelComponent_Conditional_3_Template, 1, 2, "i", 3);
|
|
739
1089
|
i0.ɵɵelementStart(4, "h3", 4);
|
|
@@ -762,11 +1112,13 @@ export class EntityRecordDetailPanelComponent {
|
|
|
762
1112
|
i0.ɵɵelement(21, "i", 12);
|
|
763
1113
|
i0.ɵɵelementEnd();
|
|
764
1114
|
i0.ɵɵconditionalCreate(22, EntityRecordDetailPanelComponent_Conditional_22_Template, 4, 1, "div", 13);
|
|
765
|
-
i0.ɵɵelementEnd()
|
|
766
|
-
i0.ɵɵ
|
|
767
|
-
i0.ɵɵ
|
|
768
|
-
i0.ɵɵ
|
|
769
|
-
i0.ɵɵ
|
|
1115
|
+
i0.ɵɵelementEnd();
|
|
1116
|
+
i0.ɵɵconditionalCreate(23, EntityRecordDetailPanelComponent_Conditional_23_Template, 7, 5, "div", 8);
|
|
1117
|
+
i0.ɵɵelementEnd();
|
|
1118
|
+
i0.ɵɵelementStart(24, "div", 15)(25, "button", 16);
|
|
1119
|
+
i0.ɵɵlistener("click", function EntityRecordDetailPanelComponent_Template_button_click_25_listener() { return ctx.onOpenRecord(); });
|
|
1120
|
+
i0.ɵɵelement(26, "i", 17);
|
|
1121
|
+
i0.ɵɵtext(27, " Open Full Record ");
|
|
770
1122
|
i0.ɵɵelementEnd()()();
|
|
771
1123
|
} if (rf & 2) {
|
|
772
1124
|
i0.ɵɵadvance(3);
|
|
@@ -781,11 +1133,13 @@ export class EntityRecordDetailPanelComponent {
|
|
|
781
1133
|
i0.ɵɵclassProp("fa-chevron-down", ctx.relationshipsSectionExpanded)("fa-chevron-right", !ctx.relationshipsSectionExpanded);
|
|
782
1134
|
i0.ɵɵadvance();
|
|
783
1135
|
i0.ɵɵconditional(ctx.relationshipsSectionExpanded ? 22 : -1);
|
|
1136
|
+
i0.ɵɵadvance();
|
|
1137
|
+
i0.ɵɵconditional(ctx.organicKeyMatches.length > 0 || ctx.isLoadingOrganicKeys ? 23 : -1);
|
|
784
1138
|
} }, dependencies: [i1.LoadingComponent, i2.PillComponent], styles: [".entity-record-card-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.panel-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.entity-icon[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.panel-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n}\n\n.section[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px 20px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n.section-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.section-icon[_ngcontent-%COMP%] {\n width: 20px;\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-right: 10px;\n}\n\n.section-title[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.loading-icon[_ngcontent-%COMP%] {\n margin-right: 8px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n}\n\n.expand-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-disabled);\n transition: transform 0.15s ease;\n}\n\n.section-content[_ngcontent-%COMP%] {\n padding: 0 20px 12px 20px;\n}\n\n.empty-section[_ngcontent-%COMP%] {\n padding: 12px 0;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n font-style: italic;\n}\n\n.relationships-loading[_ngcontent-%COMP%] {\n padding: 20px 0;\n display: flex;\n justify-content: center;\n}\n\n.field-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n.field-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.field-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 2px;\n}\n\n.field-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n word-break: break-word;\n}\n\n\n\n.field-row-pk[_ngcontent-%COMP%] {\n flex-direction: row;\n padding: 6px 0;\n}\n\n.pk-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.pk-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-disabled);\n}\n\n.pk-row[_ngcontent-%COMP%] .field-label[_ngcontent-%COMP%] {\n margin-bottom: 0;\n flex: 1;\n}\n\n.copy-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\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: var(--mj-text-disabled);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.copy-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n.copy-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.field-row-fk[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.fk-value-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fk-display-value[_ngcontent-%COMP%] {\n flex: 1;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.fk-link-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\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: var(--mj-text-disabled);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.fk-link-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n.fk-link-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n\n\n.fk-id-only[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-radius: 4px;\n padding: 4px 8px;\n}\n\n.fk-id-value[_ngcontent-%COMP%] {\n font-size: 12px;\n font-family: monospace;\n color: var(--mj-text-muted);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n\n.related-entity-group[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n border-radius: 6px;\n overflow: hidden;\n}\n.related-entity-group.expanded[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n margin-bottom: 8px;\n}\n\n\n\n.related-entity-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n gap: 8px;\n transition: background 0.15s ease;\n}\n.related-entity-header.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n.related-entity-header.clickable[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n.related-entity-header.loading[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.expand-chevron[_ngcontent-%COMP%] {\n width: 12px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n transition: transform 0.15s ease;\n}\n\n.related-entity-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:nth-child(2) {\n width: 16px;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.related-entity-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.related-entity-count[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n min-width: 24px;\n text-align: right;\n}\n\n\n\n.related-records-list[_ngcontent-%COMP%] {\n padding: 4px 8px 8px 32px;\n}\n\n.records-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.related-record-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n margin-bottom: 2px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid var(--mj-border-default);\n}\n.related-record-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 1px 4px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n.related-record-item[_ngcontent-%COMP%]:hover .record-open-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.record-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.record-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.record-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.record-open-icon[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-disabled);\n margin-left: 8px;\n flex-shrink: 0;\n transition: color 0.15s ease;\n}\n\n.view-all-link[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px;\n margin-top: 4px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n cursor: pointer;\n border-radius: 6px;\n transition: background 0.15s ease;\n}\n.view-all-link[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.panel-footer[_ngcontent-%COMP%] {\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.open-record-btn[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.15s ease;\n}\n.open-record-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n.open-record-btn[_ngcontent-%COMP%]:active {\n transform: scale(0.98);\n}"] });
|
|
785
1139
|
}
|
|
786
1140
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityRecordDetailPanelComponent, [{
|
|
787
1141
|
type: Component,
|
|
788
|
-
args: [{ standalone: false, selector: 'mj-entity-record-detail-panel', template: "<div class=\"entity-record-card-container\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title-row\">\n @if (entity?.Icon) {\n <i [class]=\"getEntityIconClass()\" class=\"entity-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ recordTitle }}</h3>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Details Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('details')\">\n <i class=\"fa-solid fa-info-circle section-icon\"></i>\n <span class=\"section-title\">Details</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"detailsSectionExpanded\" [class.fa-chevron-right]=\"!detailsSectionExpanded\"></i>\n </div>\n\n @if (detailsSectionExpanded) {\n <div class=\"section-content\">\n @for (field of displayFields; track field.name) {\n <!-- Primary Key Field - Compact with copy button -->\n @if (field.type === 'primary-key') {\n <div class=\"field-row field-row-pk\">\n <div class=\"pk-row\">\n <i class=\"fa-solid fa-key pk-icon\"></i>\n <span class=\"field-label\">{{ field.label }}</span>\n <button class=\"copy-btn\" (click)=\"copyToClipboard(field.value, $event)\" title=\"Copy ID\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n </div>\n }\n <!-- Foreign Key Field - Show friendly name with open button -->\n @else if (field.type === 'foreign-key') {\n <div class=\"field-row field-row-fk\">\n <span class=\"field-label\">{{ field.label }}</span>\n <div class=\"fk-value-row\" [class.fk-id-only]=\"!hasFriendlyName(field)\">\n @if (hasFriendlyName(field)) {\n <span class=\"field-value fk-display-value\">{{ field.displayValue }}</span>\n } @else {\n <!-- No friendly name available, show ID in muted style -->\n <span class=\"field-value fk-id-value\">{{ field.value }}</span>\n }\n <!-- Always show open button for FK fields that have a related entity -->\n @if (field.relatedEntityName) {\n <button class=\"fk-link-btn\" (click)=\"onForeignKeyClick(field, $event)\" title=\"Open {{ field.relatedEntityName }} record\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n </div>\n </div>\n }\n <!-- Enum Field - Show as pill -->\n @else if (field.type === 'enum') {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <mj-pill [value]=\"field.value\"></mj-pill>\n </div>\n }\n <!-- Regular Field -->\n @else {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <span class=\"field-value\">{{ field.value }}</span>\n </div>\n }\n }\n\n @if (displayFields.length === 0) {\n <div class=\"empty-section\">No details available</div>\n }\n </div>\n }\n </div>\n\n <!-- Relationships Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('relationships')\">\n <i class=\"fa-solid fa-project-diagram section-icon\"></i>\n <span class=\"section-title\">Related Records</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"relationshipsSectionExpanded\" [class.fa-chevron-right]=\"!relationshipsSectionExpanded\"></i>\n </div>\n\n @if (relationshipsSectionExpanded) {\n <div class=\"section-content\">\n @if (isLoadingRelationships) {\n <div class=\"relationships-loading\">\n <mj-loading text=\"Loading related records...\" size=\"small\"></mj-loading>\n </div>\n } @else if (relatedEntitiesWithRecords.length === 0) {\n <div class=\"empty-section\">No related records</div>\n } @else {\n @for (relEntity of relatedEntitiesWithRecords; track relEntity.relatedEntityName) {\n <div class=\"related-entity-group\" [class.expanded]=\"relEntity.isExpanded\">\n <!-- Header row - click to expand -->\n <div\n class=\"related-entity-header\"\n [class.clickable]=\"relEntity.count > 0\"\n (click)=\"toggleRelatedEntityExpansion(relEntity, $event)\">\n <i class=\"fa-solid expand-chevron\"\n [class.fa-chevron-down]=\"relEntity.isExpanded\"\n [class.fa-chevron-right]=\"!relEntity.isExpanded\"></i>\n <i [class]=\"getRelatedEntityIcon(relEntity)\"></i>\n <span class=\"related-entity-name\">{{ relEntity.relatedEntityName }}</span>\n <span class=\"related-entity-count\">{{ relEntity.count }}</span>\n </div>\n\n <!-- Expanded records list -->\n @if (relEntity.isExpanded) {\n <div class=\"related-records-list\">\n @if (relEntity.isLoadingRecords) {\n <div class=\"records-loading\">\n <mj-loading text=\"Loading...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n @for (rec of relEntity.records; track $index) {\n <div class=\"related-record-item\" (click)=\"onRelatedRecordClick(relEntity, rec, $event)\">\n <div class=\"record-info\">\n <span class=\"record-name\">{{ getRelatedRecordDisplayName(relEntity, rec) }}</span>\n @if (getRelatedRecordSubtitle(relEntity, rec); as subtitle) {\n <span class=\"record-subtitle\">{{ subtitle }}</span>\n }\n </div>\n <i class=\"fa-solid fa-external-link-alt record-open-icon\"></i>\n </div>\n }\n\n <!-- View All link if there are more records -->\n @if (relEntity.count > 10) {\n <div class=\"view-all-link\" (click)=\"onViewAllRelated(relEntity, $event)\">\n <span>View all {{ relEntity.count }} records</span>\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"open-record-btn\" (click)=\"onOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n </div>\n</div>\n", styles: [".entity-record-card-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.panel-title-row {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.entity-icon {\n font-size: 18px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.close-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.close-btn:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n}\n\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n}\n\n.section {\n margin-bottom: 8px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n padding: 12px 20px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n.section-header:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.section-icon {\n width: 20px;\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-right: 10px;\n}\n\n.section-title {\n flex: 1;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.loading-icon {\n margin-right: 8px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n}\n\n.expand-icon {\n font-size: 10px;\n color: var(--mj-text-disabled);\n transition: transform 0.15s ease;\n}\n\n.section-content {\n padding: 0 20px 12px 20px;\n}\n\n.empty-section {\n padding: 12px 0;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n font-style: italic;\n}\n\n.relationships-loading {\n padding: 20px 0;\n display: flex;\n justify-content: center;\n}\n\n.field-row {\n display: flex;\n flex-direction: column;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n.field-row:last-child {\n border-bottom: none;\n}\n\n.field-label {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 2px;\n}\n\n.field-value {\n font-size: 14px;\n color: var(--mj-text-secondary);\n word-break: break-word;\n}\n\n/* Primary Key Field - Compact row with key icon and copy button */\n.field-row-pk {\n flex-direction: row;\n padding: 6px 0;\n}\n\n.pk-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.pk-icon {\n font-size: 12px;\n color: var(--mj-text-disabled);\n}\n\n.pk-row .field-label {\n margin-bottom: 0;\n flex: 1;\n}\n\n.copy-btn {\n width: 28px;\n height: 28px;\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: var(--mj-text-disabled);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.copy-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n.copy-btn i {\n font-size: 12px;\n}\n\n/* Foreign Key Field - Display name with link button */\n.field-row-fk {\n padding: 8px 0;\n}\n\n.fk-value-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fk-display-value {\n flex: 1;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.fk-link-btn {\n width: 28px;\n height: 28px;\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: var(--mj-text-disabled);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.fk-link-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n.fk-link-btn i {\n font-size: 11px;\n}\n\n/* FK without friendly name - show ID in muted style */\n.fk-id-only {\n background: var(--mj-bg-surface-card);\n border-radius: 4px;\n padding: 4px 8px;\n}\n\n.fk-id-value {\n font-size: 12px;\n font-family: monospace;\n color: var(--mj-text-muted);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Related Entity Group - expandable container */\n.related-entity-group {\n margin-bottom: 4px;\n border-radius: 6px;\n overflow: hidden;\n}\n.related-entity-group.expanded {\n background: var(--mj-bg-surface-card);\n margin-bottom: 8px;\n}\n\n/* Header row */\n.related-entity-header {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n gap: 8px;\n transition: background 0.15s ease;\n}\n.related-entity-header.clickable {\n cursor: pointer;\n}\n.related-entity-header.clickable:hover {\n background: var(--mj-bg-surface-sunken);\n}\n.related-entity-header.loading {\n opacity: 0.7;\n}\n\n.expand-chevron {\n width: 12px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n transition: transform 0.15s ease;\n}\n\n.related-entity-header i:nth-child(2) {\n width: 16px;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.related-entity-name {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.related-entity-count {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n min-width: 24px;\n text-align: right;\n}\n\n/* Expanded records list */\n.related-records-list {\n padding: 4px 8px 8px 32px;\n}\n\n.records-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.related-record-item {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n margin-bottom: 2px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid var(--mj-border-default);\n}\n.related-record-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 1px 4px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n.related-record-item:hover .record-open-icon {\n color: var(--mj-brand-primary);\n}\n\n.record-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.record-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.record-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.record-open-icon {\n font-size: 11px;\n color: var(--mj-text-disabled);\n margin-left: 8px;\n flex-shrink: 0;\n transition: color 0.15s ease;\n}\n\n.view-all-link {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px;\n margin-top: 4px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n cursor: pointer;\n border-radius: 6px;\n transition: background 0.15s ease;\n}\n.view-all-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.panel-footer {\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.open-record-btn {\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.15s ease;\n}\n.open-record-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n.open-record-btn:active {\n transform: scale(0.98);\n}\n"] }]
|
|
1142
|
+
args: [{ standalone: false, selector: 'mj-entity-record-detail-panel', template: "<div class=\"entity-record-card-container\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title-row\">\n @if (entity?.Icon) {\n <i [class]=\"getEntityIconClass()\" class=\"entity-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ recordTitle }}</h3>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Details Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('details')\">\n <i class=\"fa-solid fa-info-circle section-icon\"></i>\n <span class=\"section-title\">Details</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"detailsSectionExpanded\" [class.fa-chevron-right]=\"!detailsSectionExpanded\"></i>\n </div>\n\n @if (detailsSectionExpanded) {\n <div class=\"section-content\">\n @for (field of displayFields; track field.name) {\n <!-- Primary Key Field - Compact with copy button -->\n @if (field.type === 'primary-key') {\n <div class=\"field-row field-row-pk\">\n <div class=\"pk-row\">\n <i class=\"fa-solid fa-key pk-icon\"></i>\n <span class=\"field-label\">{{ field.label }}</span>\n <button class=\"copy-btn\" (click)=\"copyToClipboard(field.value, $event)\" title=\"Copy ID\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n </div>\n }\n <!-- Foreign Key Field - Show friendly name with open button -->\n @else if (field.type === 'foreign-key') {\n <div class=\"field-row field-row-fk\">\n <span class=\"field-label\">{{ field.label }}</span>\n <div class=\"fk-value-row\" [class.fk-id-only]=\"!hasFriendlyName(field)\">\n @if (hasFriendlyName(field)) {\n <span class=\"field-value fk-display-value\">{{ field.displayValue }}</span>\n } @else {\n <!-- No friendly name available, show ID in muted style -->\n <span class=\"field-value fk-id-value\">{{ field.value }}</span>\n }\n <!-- Always show open button for FK fields that have a related entity -->\n @if (field.relatedEntityName) {\n <button class=\"fk-link-btn\" (click)=\"onForeignKeyClick(field, $event)\" title=\"Open {{ field.relatedEntityName }} record\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n </div>\n </div>\n }\n <!-- Enum Field - Show as pill -->\n @else if (field.type === 'enum') {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <mj-pill [value]=\"field.value\"></mj-pill>\n </div>\n }\n <!-- Regular Field -->\n @else {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <span class=\"field-value\">{{ field.value }}</span>\n </div>\n }\n }\n\n @if (displayFields.length === 0) {\n <div class=\"empty-section\">No details available</div>\n }\n </div>\n }\n </div>\n\n <!-- Relationships Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('relationships')\">\n <i class=\"fa-solid fa-project-diagram section-icon\"></i>\n <span class=\"section-title\">Related Records</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"relationshipsSectionExpanded\" [class.fa-chevron-right]=\"!relationshipsSectionExpanded\"></i>\n </div>\n\n @if (relationshipsSectionExpanded) {\n <div class=\"section-content\">\n @if (isLoadingRelationships) {\n <div class=\"relationships-loading\">\n <mj-loading text=\"Loading related records...\" size=\"small\"></mj-loading>\n </div>\n } @else if (relatedEntitiesWithRecords.length === 0) {\n <div class=\"empty-section\">No related records</div>\n } @else {\n @for (relEntity of relatedEntitiesWithRecords; track relEntity.relatedEntityName) {\n <div class=\"related-entity-group\" [class.expanded]=\"relEntity.isExpanded\">\n <!-- Header row - click to expand -->\n <div\n class=\"related-entity-header\"\n [class.clickable]=\"relEntity.count > 0\"\n (click)=\"toggleRelatedEntityExpansion(relEntity, $event)\">\n <i class=\"fa-solid expand-chevron\"\n [class.fa-chevron-down]=\"relEntity.isExpanded\"\n [class.fa-chevron-right]=\"!relEntity.isExpanded\"></i>\n <i [class]=\"getRelatedEntityIcon(relEntity)\"></i>\n <span class=\"related-entity-name\">{{ relEntity.relatedEntityName }}</span>\n <span class=\"related-entity-count\">{{ relEntity.count }}</span>\n </div>\n\n <!-- Expanded records list -->\n @if (relEntity.isExpanded) {\n <div class=\"related-records-list\">\n @if (relEntity.isLoadingRecords) {\n <div class=\"records-loading\">\n <mj-loading text=\"Loading...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n @for (rec of relEntity.records; track $index) {\n <div class=\"related-record-item\" (click)=\"onRelatedRecordClick(relEntity, rec, $event)\">\n <div class=\"record-info\">\n <span class=\"record-name\">{{ getRelatedRecordDisplayName(relEntity, rec) }}</span>\n @if (getRelatedRecordSubtitle(relEntity, rec); as subtitle) {\n <span class=\"record-subtitle\">{{ subtitle }}</span>\n }\n </div>\n <i class=\"fa-solid fa-external-link-alt record-open-icon\"></i>\n </div>\n }\n\n <!-- View All link if there are more records -->\n @if (relEntity.count > 10) {\n <div class=\"view-all-link\" (click)=\"onViewAllRelated(relEntity, $event)\">\n <span>View all {{ relEntity.count }} records</span>\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n\n <!-- Organic Key Matches Section -->\n @if (organicKeyMatches.length > 0 || isLoadingOrganicKeys) {\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('organicKeys')\">\n <i class=\"fa-solid fa-link section-icon\"></i>\n <span class=\"section-title\">Organic Key Matches</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"organicKeysSectionExpanded\" [class.fa-chevron-right]=\"!organicKeysSectionExpanded\"></i>\n </div>\n\n @if (organicKeysSectionExpanded) {\n <div class=\"section-content\">\n @if (isLoadingOrganicKeys) {\n <div class=\"relationships-loading\">\n <mj-loading text=\"Loading organic key matches...\" size=\"small\"></mj-loading>\n </div>\n } @else if (organicKeyMatchesWithRecords.length === 0) {\n <div class=\"empty-section\">No organic key matches</div>\n } @else {\n @for (match of organicKeyMatchesWithRecords; track match.relatedEntityName) {\n <div class=\"related-entity-group\" [class.expanded]=\"match.isExpanded\">\n <div\n class=\"related-entity-header\"\n [class.clickable]=\"match.count > 0\"\n (click)=\"toggleOrganicKeyExpansion(match, $event)\">\n <i class=\"fa-solid expand-chevron\"\n [class.fa-chevron-down]=\"match.isExpanded\"\n [class.fa-chevron-right]=\"!match.isExpanded\"></i>\n <i [class]=\"getOrganicKeyEntityIcon(match)\"></i>\n <span class=\"related-entity-name\">{{ match.relatedEntityName }}</span>\n <span class=\"related-entity-count\">{{ match.count }}</span>\n </div>\n\n @if (match.isExpanded) {\n <div class=\"related-records-list\">\n @if (match.isLoadingRecords) {\n <div class=\"records-loading\">\n <mj-loading text=\"Loading...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n @for (rec of match.records; track $index) {\n <div class=\"related-record-item\" (click)=\"onOrganicKeyRecordClick(match, rec, $event)\">\n <div class=\"record-info\">\n <span class=\"record-name\">{{ getOrganicKeyRecordDisplayName(match, rec) }}</span>\n @if (getOrganicKeyRecordSubtitle(match, rec); as subtitle) {\n <span class=\"record-subtitle\">{{ subtitle }}</span>\n }\n </div>\n <i class=\"fa-solid fa-external-link-alt record-open-icon\"></i>\n </div>\n }\n\n @if (match.count > 10) {\n <div class=\"view-all-link\" (click)=\"onViewAllOrganicKey(match, $event)\">\n <span>View all {{ match.count }} records</span>\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"open-record-btn\" (click)=\"onOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n </div>\n</div>\n", styles: [".entity-record-card-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.panel-title-row {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.entity-icon {\n font-size: 18px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.close-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.close-btn:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n}\n\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n}\n\n.section {\n margin-bottom: 8px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n padding: 12px 20px;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s ease;\n}\n.section-header:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.section-icon {\n width: 20px;\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-right: 10px;\n}\n\n.section-title {\n flex: 1;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.loading-icon {\n margin-right: 8px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n}\n\n.expand-icon {\n font-size: 10px;\n color: var(--mj-text-disabled);\n transition: transform 0.15s ease;\n}\n\n.section-content {\n padding: 0 20px 12px 20px;\n}\n\n.empty-section {\n padding: 12px 0;\n text-align: center;\n color: var(--mj-text-disabled);\n font-size: 13px;\n font-style: italic;\n}\n\n.relationships-loading {\n padding: 20px 0;\n display: flex;\n justify-content: center;\n}\n\n.field-row {\n display: flex;\n flex-direction: column;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-bg-surface-card);\n}\n.field-row:last-child {\n border-bottom: none;\n}\n\n.field-label {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 2px;\n}\n\n.field-value {\n font-size: 14px;\n color: var(--mj-text-secondary);\n word-break: break-word;\n}\n\n/* Primary Key Field - Compact row with key icon and copy button */\n.field-row-pk {\n flex-direction: row;\n padding: 6px 0;\n}\n\n.pk-row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.pk-icon {\n font-size: 12px;\n color: var(--mj-text-disabled);\n}\n\n.pk-row .field-label {\n margin-bottom: 0;\n flex: 1;\n}\n\n.copy-btn {\n width: 28px;\n height: 28px;\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: var(--mj-text-disabled);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.copy-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n.copy-btn i {\n font-size: 12px;\n}\n\n/* Foreign Key Field - Display name with link button */\n.field-row-fk {\n padding: 8px 0;\n}\n\n.fk-value-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fk-display-value {\n flex: 1;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.fk-link-btn {\n width: 28px;\n height: 28px;\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: var(--mj-text-disabled);\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.fk-link-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n.fk-link-btn i {\n font-size: 11px;\n}\n\n/* FK without friendly name - show ID in muted style */\n.fk-id-only {\n background: var(--mj-bg-surface-card);\n border-radius: 4px;\n padding: 4px 8px;\n}\n\n.fk-id-value {\n font-size: 12px;\n font-family: monospace;\n color: var(--mj-text-muted);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Related Entity Group - expandable container */\n.related-entity-group {\n margin-bottom: 4px;\n border-radius: 6px;\n overflow: hidden;\n}\n.related-entity-group.expanded {\n background: var(--mj-bg-surface-card);\n margin-bottom: 8px;\n}\n\n/* Header row */\n.related-entity-header {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n gap: 8px;\n transition: background 0.15s ease;\n}\n.related-entity-header.clickable {\n cursor: pointer;\n}\n.related-entity-header.clickable:hover {\n background: var(--mj-bg-surface-sunken);\n}\n.related-entity-header.loading {\n opacity: 0.7;\n}\n\n.expand-chevron {\n width: 12px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n transition: transform 0.15s ease;\n}\n\n.related-entity-header i:nth-child(2) {\n width: 16px;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.related-entity-name {\n flex: 1;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.related-entity-count {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-muted);\n min-width: 24px;\n text-align: right;\n}\n\n/* Expanded records list */\n.related-records-list {\n padding: 4px 8px 8px 32px;\n}\n\n.records-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n}\n\n.related-record-item {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n margin-bottom: 2px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n border: 1px solid var(--mj-border-default);\n}\n.related-record-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 1px 4px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n.related-record-item:hover .record-open-icon {\n color: var(--mj-brand-primary);\n}\n\n.record-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.record-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.record-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.record-open-icon {\n font-size: 11px;\n color: var(--mj-text-disabled);\n margin-left: 8px;\n flex-shrink: 0;\n transition: color 0.15s ease;\n}\n\n.view-all-link {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 10px;\n margin-top: 4px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n cursor: pointer;\n border-radius: 6px;\n transition: background 0.15s ease;\n}\n.view-all-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.panel-footer {\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.open-record-btn {\n width: 100%;\n padding: 12px 16px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.15s ease;\n}\n.open-record-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n.open-record-btn:active {\n transform: scale(0.98);\n}\n"] }]
|
|
789
1143
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }], { entity: [{
|
|
790
1144
|
type: Input
|
|
791
1145
|
}], record: [{
|
|
@@ -801,5 +1155,5 @@ export class EntityRecordDetailPanelComponent {
|
|
|
801
1155
|
}], openForeignKeyRecord: [{
|
|
802
1156
|
type: Output
|
|
803
1157
|
}] }); })();
|
|
804
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityRecordDetailPanelComponent, { className: "EntityRecordDetailPanelComponent", filePath: "src/lib/entity-record-detail-panel/entity-record-detail-panel.component.ts", lineNumber:
|
|
1158
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityRecordDetailPanelComponent, { className: "EntityRecordDetailPanelComponent", filePath: "src/lib/entity-record-detail-panel/entity-record-detail-panel.component.ts", lineNumber: 95 }); })();
|
|
805
1159
|
//# sourceMappingURL=entity-record-detail-panel.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-record-detail-panel.component.js","sourceRoot":"","sources":["../../../src/lib/entity-record-detail-panel/entity-record-detail-panel.component.ts","../../../src/lib/entity-record-detail-panel/entity-record-detail-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ChangeDetectorRef, NgZone } from '@angular/core';\nimport { EntityInfo, EntityRelationshipInfo, RunView, Metadata, RunViewParams, EntityFieldValueListType, EntityFieldInfo, CompositeKey } from '@memberjunction/core';\nimport { buildCompositeKey, buildPkString } from '../utils/record.util';\n\ninterface RelatedEntityData {\n relationship: EntityRelationshipInfo;\n relatedEntityName: string;\n count: number;\n isExpanded: boolean;\n records: Record<string, unknown>[];\n isLoadingRecords: boolean;\n}\n\n/**\n * Field display types for categorizing how to render each field\n */\ntype FieldDisplayType = 'primary-key' | 'foreign-key' | 'enum' | 'regular';\n\n/**\n * Enhanced field display info with type categorization\n */\ninterface FieldDisplay {\n type: FieldDisplayType;\n name: string;\n label: string;\n value: string;\n // For FK fields - the display name from the virtual/mapped field\n displayValue?: string;\n // For FK fields - related entity info for navigation\n relatedEntityName?: string;\n relatedRecordId?: string;\n}\n\n/**\n * Event emitted when navigating to a related entity\n */\nexport interface NavigateToRelatedEvent {\n entityName: string;\n filter: string;\n}\n\n/**\n * Event emitted when opening a related record\n */\nexport interface OpenRelatedRecordEvent {\n entityName: string;\n record: Record<string, unknown>;\n}\n\n/**\n * Event emitted when opening a foreign key record\n */\nexport interface OpenForeignKeyRecordEvent {\n entityName: string;\n recordId: string;\n}\n\n/**\n * EntityRecordDetailPanelComponent - A reusable panel for displaying entity record details\n *\n * This component provides a detail panel view for entity records with:\n * - Primary key display with copy functionality\n * - Foreign key fields showing friendly names with navigation\n * - Enum fields displayed as pills\n * - Related entities with expandable record lists\n * - Configurable sections for details and relationships\n *\n * @example\n * ```html\n * <mj-entity-record-detail-panel\n * [entity]=\"selectedEntity\"\n * [record]=\"selectedRecord\"\n * (close)=\"onClosePanel()\"\n * (openRecord)=\"onOpenRecord($event)\"\n * (navigateToRelated)=\"onNavigateToRelated($event)\">\n * </mj-entity-record-detail-panel>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-record-detail-panel',\n templateUrl: './entity-record-detail-panel.component.html',\n styleUrls: ['./entity-record-detail-panel.component.css']\n})\nexport class EntityRecordDetailPanelComponent implements OnChanges {\n @Input() entity: EntityInfo | null = null;\n @Input() record: Record<string, unknown> | null = null;\n\n @Output() close = new EventEmitter<void>();\n @Output() openRecord = new EventEmitter<Record<string, unknown>>();\n @Output() navigateToRelated = new EventEmitter<NavigateToRelatedEvent>();\n @Output() openRelatedRecord = new EventEmitter<OpenRelatedRecordEvent>();\n @Output() openForeignKeyRecord = new EventEmitter<OpenForeignKeyRecordEvent>();\n\n // Related entity counts\n public relatedEntities: RelatedEntityData[] = [];\n public isLoadingRelationships = false;\n\n private metadata = new Metadata();\n\n // Sections expanded state\n public detailsSectionExpanded = true;\n public relationshipsSectionExpanded = true;\n\n constructor(private cdr: ChangeDetectorRef, private ngZone: NgZone) {}\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['record'] && this.record && this.entity) {\n this.loadRelationshipCounts();\n }\n }\n\n /**\n * Load counts for related entities using batch RunViews call\n */\n private async loadRelationshipCounts(): Promise<void> {\n if (!this.entity || !this.record) return;\n\n this.isLoadingRelationships = true;\n this.relatedEntities = [];\n\n // Get relationships where this entity is the related entity (foreign keys pointing TO this record)\n const relationships = this.entity.RelatedEntities;\n\n if (relationships.length === 0) {\n this.isLoadingRelationships = false;\n return;\n }\n\n // Build a CompositeKey for the current record\n const compositeKey = buildCompositeKey(this.record, this.entity);\n\n // Get the first PK value for the join field filter\n const pkValue = compositeKey.KeyValuePairs[0]?.Value;\n if (!pkValue) {\n this.isLoadingRelationships = false;\n return;\n }\n\n // Build batch query params for all relationships\n const viewParams: RunViewParams[] = relationships.map(rel => ({\n EntityName: rel.RelatedEntity,\n ExtraFilter: `${rel.RelatedEntityJoinField}='${pkValue}'`,\n ResultType: 'count_only'\n }));\n\n try {\n const rv = new RunView();\n const results = await rv.RunViews(viewParams);\n\n // Map results back to relationship data\n this.relatedEntities = relationships.map((rel, index) => {\n const result = results[index];\n return {\n relationship: rel,\n relatedEntityName: rel.RelatedEntity,\n count: result.Success ? result.TotalRowCount : 0,\n isExpanded: false,\n records: [],\n isLoadingRecords: false\n };\n });\n } catch (error) {\n console.warn('Failed to load relationship counts:', error);\n // Initialize with zero counts on error\n this.relatedEntities = relationships.map(rel => ({\n relationship: rel,\n relatedEntityName: rel.RelatedEntity,\n count: 0,\n isExpanded: false,\n records: [],\n isLoadingRecords: false\n }));\n } finally {\n this.ngZone.run(() => {\n this.isLoadingRelationships = false;\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Get key fields to display in details section, categorized by type\n */\n get displayFields(): FieldDisplay[] {\n if (!this.entity || !this.record) return [];\n\n const fields: FieldDisplay[] = [];\n const excludePatterns = ['__mj_', 'password', 'secret', 'token'];\n\n for (const field of this.entity.Fields) {\n // Skip system fields and sensitive fields\n if (excludePatterns.some(p => field.Name.toLowerCase().includes(p))) continue;\n // Skip very long text fields (but not FK fields which are usually GUIDs)\n if (field.Length && field.Length > 500 && !field.RelatedEntityID) continue;\n\n const value = this.record[field.Name];\n\n // Handle Primary Key fields specially\n if (field.IsPrimaryKey) {\n fields.push({\n type: 'primary-key',\n name: field.Name,\n label: this.formatFieldLabel(field),\n value: value !== null && value !== undefined ? String(value) : ''\n });\n continue;\n }\n\n // Handle Foreign Key fields - show the related record name instead of ID\n if (field.RelatedEntityID && field.RelatedEntityID.length > 0) {\n const fkDisplay = this.buildForeignKeyDisplay(field, value);\n if (fkDisplay) {\n fields.push(fkDisplay);\n }\n continue;\n }\n\n // Skip empty values for regular fields\n if (value === null || value === undefined || String(value).trim() === '') continue;\n\n // Limit regular fields to reasonable number\n if (fields.filter(f => f.type === 'regular' || f.type === 'enum').length >= 10) continue;\n\n // Check if this field has enumerated values\n const isEnum = field.ValueListTypeEnum !== EntityFieldValueListType.None &&\n field.EntityFieldValues.length > 0;\n\n fields.push({\n type: isEnum ? 'enum' : 'regular',\n name: field.Name,\n label: this.formatFieldLabel(field),\n value: this.formatFieldValue(value, field.Name)\n });\n }\n\n return fields;\n }\n\n /**\n * Build display info for a foreign key field\n * Uses RelatedEntityNameFieldMap to get the human-readable name\n * Label comes from the virtual field's DisplayNameOrName (e.g., \"Template\" not \"Template ID\")\n */\n private buildForeignKeyDisplay(field: EntityFieldInfo, value: unknown): FieldDisplay | null {\n if (value === null || value === undefined || String(value).trim() === '') {\n return null;\n }\n\n const fkValue = String(value);\n let displayValue = fkValue;\n let label = field.DisplayNameOrName; // Fallback to FK field's label\n\n // Try to get the display name from the mapped field\n // RelatedEntityNameFieldMap tells us which field contains the name of the related record\n if (field.RelatedEntityNameFieldMap && field.RelatedEntityNameFieldMap.trim().length > 0) {\n const mappedValue = this.record![field.RelatedEntityNameFieldMap];\n if (mappedValue !== null && mappedValue !== undefined && String(mappedValue).trim() !== '') {\n displayValue = String(mappedValue);\n }\n // Use the mapped field's DisplayNameOrName for the label\n const mappedField = this.entity!.Fields.find(f => f.Name === field.RelatedEntityNameFieldMap);\n if (mappedField) {\n label = mappedField.DisplayNameOrName;\n }\n } else {\n // Fallback: try to find a virtual field with the same name minus \"ID\" suffix\n // e.g., for \"TemplateID\", look for \"Template\" field\n const baseName = field.Name.replace(/ID$/i, '');\n if (baseName !== field.Name) {\n const virtualField = this.entity!.Fields.find(f =>\n f.Name.toLowerCase() === baseName.toLowerCase() && f.IsVirtual\n );\n if (virtualField) {\n const virtualValue = this.record![virtualField.Name];\n if (virtualValue !== null && virtualValue !== undefined && String(virtualValue).trim() !== '') {\n displayValue = String(virtualValue);\n }\n // Use the virtual field's DisplayNameOrName for the label\n label = virtualField.DisplayNameOrName;\n }\n }\n }\n\n return {\n type: 'foreign-key',\n name: field.Name,\n label: label,\n value: fkValue,\n displayValue: displayValue,\n relatedEntityName: field.RelatedEntity || undefined,\n relatedRecordId: fkValue\n };\n }\n\n /**\n * Format field name to display label using EntityFieldInfo's built-in property\n */\n private formatFieldLabel(field: EntityFieldInfo): string {\n return field.DisplayNameOrName;\n }\n\n /**\n * Format field value for display\n */\n private formatFieldValue(value: unknown, fieldName: string): string {\n if (value === null || value === undefined) return '-';\n\n // Handle dates\n if (value instanceof Date) {\n return value.toLocaleDateString();\n }\n\n // Handle booleans\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No';\n }\n\n // Handle numbers that look like currency\n if (typeof value === 'number') {\n const nameLower = fieldName.toLowerCase();\n if (nameLower.includes('amount') ||\n nameLower.includes('price') ||\n nameLower.includes('cost') ||\n nameLower.includes('total') ||\n nameLower.includes('value')) {\n return `$${value.toLocaleString()}`;\n }\n return value.toLocaleString();\n }\n\n const strValue = String(value);\n\n // Truncate long strings\n if (strValue.length > 100) {\n return strValue.substring(0, 100) + '...';\n }\n\n return strValue;\n }\n\n /**\n * Get record title\n */\n get recordTitle(): string {\n if (!this.entity || !this.record) return 'Record';\n\n if (this.entity.NameField) {\n const name = this.record[this.entity.NameField.Name];\n if (name) return String(name);\n }\n\n return buildPkString(this.record, this.entity);\n }\n\n /**\n * Handle close button click\n */\n onClose(): void {\n this.close.emit();\n }\n\n /**\n * Handle open record button click\n */\n onOpenRecord(): void {\n if (this.record) {\n this.openRecord.emit(this.record);\n }\n }\n\n /**\n * Copy primary key value to clipboard\n */\n copyToClipboard(value: string, event: Event): void {\n event.stopPropagation();\n navigator.clipboard.writeText(value).then(() => {\n // Could add a toast notification here\n console.log('Copied to clipboard:', value);\n }).catch(err => {\n console.error('Failed to copy:', err);\n });\n }\n\n /**\n * Open a foreign key record (FK link click)\n * Emits openForeignKeyRecord event for parent to handle opening the record\n */\n onForeignKeyClick(field: FieldDisplay, event: Event): void {\n event.stopPropagation();\n if (field.relatedEntityName && field.relatedRecordId) {\n this.openForeignKeyRecord.emit({\n entityName: field.relatedEntityName,\n recordId: field.relatedRecordId\n });\n }\n }\n\n /**\n * Check if a FK display value is different from the raw ID (i.e., we have a name to show)\n */\n hasFriendlyName(field: FieldDisplay): boolean {\n return field.type === 'foreign-key' &&\n field.displayValue !== undefined &&\n field.displayValue !== field.value;\n }\n\n /**\n * Toggle expansion of related entity section and load records if needed\n */\n async toggleRelatedEntityExpansion(relEntity: RelatedEntityData, event: Event): Promise<void> {\n event.stopPropagation();\n\n if (relEntity.count === 0) return;\n\n relEntity.isExpanded = !relEntity.isExpanded;\n\n // Load records on first expansion\n if (relEntity.isExpanded && relEntity.records.length === 0 && !relEntity.isLoadingRecords) {\n await this.loadRelatedRecords(relEntity);\n }\n }\n\n /**\n * Load actual records for a related entity\n */\n private async loadRelatedRecords(relEntity: RelatedEntityData): Promise<void> {\n if (!this.record || !this.entity) return;\n\n const compositeKey = buildCompositeKey(this.record, this.entity);\n const pkValue = compositeKey.KeyValuePairs[0]?.Value;\n if (!pkValue) return;\n\n relEntity.isLoadingRecords = true;\n this.cdr.detectChanges();\n\n try {\n const rv = new RunView();\n // Look up related entity info to compute fields\n const relatedEntityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relationship.RelatedEntity);\n const fields = relatedEntityInfo\n ? [...relatedEntityInfo.PrimaryKeys.map(pk => pk.Name),\n ...(relatedEntityInfo.NameField ? [relatedEntityInfo.NameField.Name] : []),\n ...relatedEntityInfo.Fields.filter(f => f.DefaultInView).map(f => f.Name)]\n : undefined;\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: relEntity.relationship.RelatedEntity,\n ExtraFilter: `${relEntity.relationship.RelatedEntityJoinField}='${pkValue}'`,\n ResultType: 'simple',\n ...(fields ? { Fields: fields } : {}),\n MaxRows: 10 // Limit inline display to 10 records\n });\n\n if (result.Success) {\n relEntity.records = result.Results;\n }\n } catch (error) {\n console.warn(`Failed to load records for ${relEntity.relatedEntityName}:`, error);\n } finally {\n this.ngZone.run(() => {\n relEntity.isLoadingRecords = false;\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Handle click on individual related record - opens in new tab\n */\n onRelatedRecordClick(relEntity: RelatedEntityData, record: Record<string, unknown>, event: Event): void {\n event.stopPropagation();\n this.openRelatedRecord.emit({\n entityName: relEntity.relatedEntityName,\n record\n });\n }\n\n /**\n * Navigate to view all related records (when count > 10)\n */\n onViewAllRelated(relEntity: RelatedEntityData, event: Event): void {\n event.stopPropagation();\n\n if (!this.record || !this.entity) return;\n\n const compositeKey = buildCompositeKey(this.record, this.entity);\n const pkValue = compositeKey.KeyValuePairs[0]?.Value;\n if (!pkValue) return;\n\n this.navigateToRelated.emit({\n entityName: relEntity.relatedEntityName,\n filter: `${relEntity.relationship.RelatedEntityJoinField}='${pkValue}'`\n });\n }\n\n /**\n * Get display name for a related record\n */\n getRelatedRecordDisplayName(relEntity: RelatedEntityData, record: Record<string, unknown>): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relatedEntityName);\n if (entityInfo?.NameField) {\n const name = record[entityInfo.NameField.Name];\n if (name) return String(name);\n }\n if (entityInfo) {\n return buildPkString(record, entityInfo);\n }\n return 'Record';\n }\n\n /**\n * Get subtitle/secondary info for a related record\n */\n getRelatedRecordSubtitle(relEntity: RelatedEntityData, record: Record<string, unknown>): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relatedEntityName);\n if (!entityInfo) return '';\n\n // Look for common subtitle fields\n const subtitleFieldNames = ['Description', 'Status', 'Type', 'Email', 'Date', 'Amount', 'Total'];\n for (const fieldName of subtitleFieldNames) {\n const field = entityInfo.Fields.find(f =>\n f.Name.includes(fieldName) && f.Name !== entityInfo.NameField?.Name\n );\n if (field) {\n const value = record[field.Name];\n if (value !== null && value !== undefined) {\n return this.formatFieldValue(value, field.Name);\n }\n }\n }\n return '';\n }\n\n /**\n * Toggle section expansion\n */\n toggleSection(section: 'details' | 'relationships'): void {\n if (section === 'details') {\n this.detailsSectionExpanded = !this.detailsSectionExpanded;\n } else {\n this.relationshipsSectionExpanded = !this.relationshipsSectionExpanded;\n }\n }\n\n /**\n * Get only related entities that have records (count > 0)\n */\n get relatedEntitiesWithRecords(): RelatedEntityData[] {\n return this.relatedEntities.filter(r => r.count > 0);\n }\n\n /**\n * Get icon for related entity by looking up EntityInfo from Metadata\n */\n getRelatedEntityIcon(relEntity: RelatedEntityData): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relatedEntityName);\n if (entityInfo?.Icon) {\n return this.formatEntityIcon(entityInfo.Icon);\n }\n return 'fa-solid fa-table';\n }\n\n /**\n * Get the icon class for the current entity\n */\n getEntityIconClass(): string {\n if (!this.entity?.Icon) {\n return 'fa-solid fa-table';\n }\n return this.formatEntityIcon(this.entity.Icon);\n }\n\n /**\n * Format entity icon to ensure proper Font Awesome class format\n */\n private formatEntityIcon(icon: string): string {\n if (!icon) {\n return 'fa-solid fa-table';\n }\n // If icon already has fa- prefix, use it as-is\n if (icon.startsWith('fa-') || icon.startsWith('fa ')) {\n // Ensure it has a style prefix (fa-solid, fa-regular, etc.)\n if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||\n icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||\n icon.startsWith('fa ')) {\n return icon;\n }\n // It's just \"fa-something\", add fa-solid prefix\n return `fa-solid ${icon}`;\n }\n // Check if it's just an icon name like \"table\" or \"users\"\n return `fa-solid fa-${icon}`;\n }\n}\n","<div class=\"entity-record-card-container\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title-row\">\n @if (entity?.Icon) {\n <i [class]=\"getEntityIconClass()\" class=\"entity-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ recordTitle }}</h3>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Details Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('details')\">\n <i class=\"fa-solid fa-info-circle section-icon\"></i>\n <span class=\"section-title\">Details</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"detailsSectionExpanded\" [class.fa-chevron-right]=\"!detailsSectionExpanded\"></i>\n </div>\n\n @if (detailsSectionExpanded) {\n <div class=\"section-content\">\n @for (field of displayFields; track field.name) {\n <!-- Primary Key Field - Compact with copy button -->\n @if (field.type === 'primary-key') {\n <div class=\"field-row field-row-pk\">\n <div class=\"pk-row\">\n <i class=\"fa-solid fa-key pk-icon\"></i>\n <span class=\"field-label\">{{ field.label }}</span>\n <button class=\"copy-btn\" (click)=\"copyToClipboard(field.value, $event)\" title=\"Copy ID\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n </div>\n }\n <!-- Foreign Key Field - Show friendly name with open button -->\n @else if (field.type === 'foreign-key') {\n <div class=\"field-row field-row-fk\">\n <span class=\"field-label\">{{ field.label }}</span>\n <div class=\"fk-value-row\" [class.fk-id-only]=\"!hasFriendlyName(field)\">\n @if (hasFriendlyName(field)) {\n <span class=\"field-value fk-display-value\">{{ field.displayValue }}</span>\n } @else {\n <!-- No friendly name available, show ID in muted style -->\n <span class=\"field-value fk-id-value\">{{ field.value }}</span>\n }\n <!-- Always show open button for FK fields that have a related entity -->\n @if (field.relatedEntityName) {\n <button class=\"fk-link-btn\" (click)=\"onForeignKeyClick(field, $event)\" title=\"Open {{ field.relatedEntityName }} record\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n </div>\n </div>\n }\n <!-- Enum Field - Show as pill -->\n @else if (field.type === 'enum') {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <mj-pill [value]=\"field.value\"></mj-pill>\n </div>\n }\n <!-- Regular Field -->\n @else {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <span class=\"field-value\">{{ field.value }}</span>\n </div>\n }\n }\n\n @if (displayFields.length === 0) {\n <div class=\"empty-section\">No details available</div>\n }\n </div>\n }\n </div>\n\n <!-- Relationships Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('relationships')\">\n <i class=\"fa-solid fa-project-diagram section-icon\"></i>\n <span class=\"section-title\">Related Records</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"relationshipsSectionExpanded\" [class.fa-chevron-right]=\"!relationshipsSectionExpanded\"></i>\n </div>\n\n @if (relationshipsSectionExpanded) {\n <div class=\"section-content\">\n @if (isLoadingRelationships) {\n <div class=\"relationships-loading\">\n <mj-loading text=\"Loading related records...\" size=\"small\"></mj-loading>\n </div>\n } @else if (relatedEntitiesWithRecords.length === 0) {\n <div class=\"empty-section\">No related records</div>\n } @else {\n @for (relEntity of relatedEntitiesWithRecords; track relEntity.relatedEntityName) {\n <div class=\"related-entity-group\" [class.expanded]=\"relEntity.isExpanded\">\n <!-- Header row - click to expand -->\n <div\n class=\"related-entity-header\"\n [class.clickable]=\"relEntity.count > 0\"\n (click)=\"toggleRelatedEntityExpansion(relEntity, $event)\">\n <i class=\"fa-solid expand-chevron\"\n [class.fa-chevron-down]=\"relEntity.isExpanded\"\n [class.fa-chevron-right]=\"!relEntity.isExpanded\"></i>\n <i [class]=\"getRelatedEntityIcon(relEntity)\"></i>\n <span class=\"related-entity-name\">{{ relEntity.relatedEntityName }}</span>\n <span class=\"related-entity-count\">{{ relEntity.count }}</span>\n </div>\n\n <!-- Expanded records list -->\n @if (relEntity.isExpanded) {\n <div class=\"related-records-list\">\n @if (relEntity.isLoadingRecords) {\n <div class=\"records-loading\">\n <mj-loading text=\"Loading...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n @for (rec of relEntity.records; track $index) {\n <div class=\"related-record-item\" (click)=\"onRelatedRecordClick(relEntity, rec, $event)\">\n <div class=\"record-info\">\n <span class=\"record-name\">{{ getRelatedRecordDisplayName(relEntity, rec) }}</span>\n @if (getRelatedRecordSubtitle(relEntity, rec); as subtitle) {\n <span class=\"record-subtitle\">{{ subtitle }}</span>\n }\n </div>\n <i class=\"fa-solid fa-external-link-alt record-open-icon\"></i>\n </div>\n }\n\n <!-- View All link if there are more records -->\n @if (relEntity.count > 10) {\n <div class=\"view-all-link\" (click)=\"onViewAllRelated(relEntity, $event)\">\n <span>View all {{ relEntity.count }} records</span>\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"open-record-btn\" (click)=\"onOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n </div>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"entity-record-detail-panel.component.js","sourceRoot":"","sources":["../../../src/lib/entity-record-detail-panel/entity-record-detail-panel.component.ts","../../../src/lib/entity-record-detail-panel/entity-record-detail-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ChangeDetectorRef, NgZone } from '@angular/core';\nimport { EntityInfo, EntityRelationshipInfo, EntityOrganicKeyInfo, EntityOrganicKeyRelatedEntityInfo, RunView, Metadata, RunViewParams, EntityFieldValueListType, EntityFieldInfo, CompositeKey } from '@memberjunction/core';\nimport { buildCompositeKey, buildPkString } from '../utils/record.util';\n\ninterface RelatedEntityData {\n relationship: EntityRelationshipInfo;\n relatedEntityName: string;\n count: number;\n isExpanded: boolean;\n records: Record<string, unknown>[];\n isLoadingRecords: boolean;\n}\n\ninterface OrganicKeyMatchData {\n organicKey: EntityOrganicKeyInfo;\n relatedEntity: EntityOrganicKeyRelatedEntityInfo;\n relatedEntityName: string;\n count: number;\n isExpanded: boolean;\n records: Record<string, unknown>[];\n isLoadingRecords: boolean;\n}\n\n/**\n * Field display types for categorizing how to render each field\n */\ntype FieldDisplayType = 'primary-key' | 'foreign-key' | 'enum' | 'regular';\n\n/**\n * Enhanced field display info with type categorization\n */\ninterface FieldDisplay {\n type: FieldDisplayType;\n name: string;\n label: string;\n value: string;\n // For FK fields - the display name from the virtual/mapped field\n displayValue?: string;\n // For FK fields - related entity info for navigation\n relatedEntityName?: string;\n relatedRecordId?: string;\n}\n\n/**\n * Event emitted when navigating to a related entity\n */\nexport interface NavigateToRelatedEvent {\n entityName: string;\n filter: string;\n}\n\n/**\n * Event emitted when opening a related record\n */\nexport interface OpenRelatedRecordEvent {\n entityName: string;\n record: Record<string, unknown>;\n}\n\n/**\n * Event emitted when opening a foreign key record\n */\nexport interface OpenForeignKeyRecordEvent {\n entityName: string;\n recordId: string;\n}\n\n/**\n * EntityRecordDetailPanelComponent - A reusable panel for displaying entity record details\n *\n * This component provides a detail panel view for entity records with:\n * - Primary key display with copy functionality\n * - Foreign key fields showing friendly names with navigation\n * - Enum fields displayed as pills\n * - Related entities with expandable record lists\n * - Configurable sections for details and relationships\n *\n * @example\n * ```html\n * <mj-entity-record-detail-panel\n * [entity]=\"selectedEntity\"\n * [record]=\"selectedRecord\"\n * (close)=\"onClosePanel()\"\n * (openRecord)=\"onOpenRecord($event)\"\n * (navigateToRelated)=\"onNavigateToRelated($event)\">\n * </mj-entity-record-detail-panel>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-record-detail-panel',\n templateUrl: './entity-record-detail-panel.component.html',\n styleUrls: ['./entity-record-detail-panel.component.css']\n})\nexport class EntityRecordDetailPanelComponent implements OnChanges {\n @Input() entity: EntityInfo | null = null;\n @Input() record: Record<string, unknown> | null = null;\n\n @Output() close = new EventEmitter<void>();\n @Output() openRecord = new EventEmitter<Record<string, unknown>>();\n @Output() navigateToRelated = new EventEmitter<NavigateToRelatedEvent>();\n @Output() openRelatedRecord = new EventEmitter<OpenRelatedRecordEvent>();\n @Output() openForeignKeyRecord = new EventEmitter<OpenForeignKeyRecordEvent>();\n\n // Related entity counts\n public relatedEntities: RelatedEntityData[] = [];\n public isLoadingRelationships = false;\n\n // Organic key match counts\n public organicKeyMatches: OrganicKeyMatchData[] = [];\n public isLoadingOrganicKeys = false;\n\n private metadata = new Metadata();\n\n // Sections expanded state\n public detailsSectionExpanded = true;\n public relationshipsSectionExpanded = true;\n public organicKeysSectionExpanded = true;\n\n constructor(private cdr: ChangeDetectorRef, private ngZone: NgZone) {}\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['record'] && this.record && this.entity) {\n this.loadRelationshipCounts();\n this.loadOrganicKeyCounts();\n }\n }\n\n /**\n * Load counts for related entities using batch RunViews call\n */\n private async loadRelationshipCounts(): Promise<void> {\n if (!this.entity || !this.record) return;\n\n this.isLoadingRelationships = true;\n this.relatedEntities = [];\n\n // Get relationships where this entity is the related entity (foreign keys pointing TO this record)\n const relationships = this.entity.RelatedEntities;\n\n if (relationships.length === 0) {\n this.isLoadingRelationships = false;\n return;\n }\n\n // Build a CompositeKey for the current record\n const compositeKey = buildCompositeKey(this.record, this.entity);\n\n // Get the first PK value for the join field filter\n const pkValue = compositeKey.KeyValuePairs[0]?.Value;\n if (!pkValue) {\n this.isLoadingRelationships = false;\n return;\n }\n\n // Build batch query params for all relationships\n const viewParams: RunViewParams[] = relationships.map(rel => ({\n EntityName: rel.RelatedEntity,\n ExtraFilter: `${rel.RelatedEntityJoinField}='${pkValue}'`,\n ResultType: 'count_only'\n }));\n\n try {\n const rv = new RunView();\n const results = await rv.RunViews(viewParams);\n\n // Map results back to relationship data\n this.relatedEntities = relationships.map((rel, index) => {\n const result = results[index];\n return {\n relationship: rel,\n relatedEntityName: rel.RelatedEntity,\n count: result.Success ? result.TotalRowCount : 0,\n isExpanded: false,\n records: [],\n isLoadingRecords: false\n };\n });\n } catch (error) {\n console.warn('Failed to load relationship counts:', error);\n // Initialize with zero counts on error\n this.relatedEntities = relationships.map(rel => ({\n relationship: rel,\n relatedEntityName: rel.RelatedEntity,\n count: 0,\n isExpanded: false,\n records: [],\n isLoadingRecords: false\n }));\n } finally {\n this.ngZone.run(() => {\n this.isLoadingRelationships = false;\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Load counts for organic key matches using batch RunViews call.\n * Builds query filters using EntityInfo.BuildOrganicKeyViewParams for each related entity.\n */\n private async loadOrganicKeyCounts(): Promise<void> {\n if (!this.entity || !this.record) return;\n\n const organicKeys = this.entity.OrganicKeys;\n if (!organicKeys || organicKeys.length === 0) {\n this.organicKeyMatches = [];\n return;\n }\n\n // Flatten all organic key related entities\n const allPairs: { organicKey: EntityOrganicKeyInfo; relatedEntity: EntityOrganicKeyRelatedEntityInfo }[] = [];\n for (const ok of organicKeys) {\n for (const re of ok.RelatedEntities) {\n allPairs.push({ organicKey: ok, relatedEntity: re });\n }\n }\n\n if (allPairs.length === 0) {\n this.organicKeyMatches = [];\n return;\n }\n\n this.isLoadingOrganicKeys = true;\n this.organicKeyMatches = [];\n\n // Build a mock BaseEntity-like object for BuildOrganicKeyViewParams\n // The static method only calls record.Get(fieldName), so we can duck-type it\n const mockRecord = {\n Get: (fieldName: string) => this.record ? this.record[fieldName] ?? null : null,\n EntityInfo: this.entity,\n };\n\n // Build batch query params\n const viewParams: RunViewParams[] = allPairs.map(pair => {\n const params = EntityInfo.BuildOrganicKeyViewParams(\n mockRecord as never,\n pair.relatedEntity,\n pair.organicKey,\n );\n params.ResultType = 'count_only';\n return params;\n });\n\n try {\n const rv = new RunView();\n const results = await rv.RunViews(viewParams);\n\n this.organicKeyMatches = allPairs.map((pair, index) => {\n const result = results[index];\n return {\n organicKey: pair.organicKey,\n relatedEntity: pair.relatedEntity,\n relatedEntityName: pair.relatedEntity.DisplayName || pair.relatedEntity.RelatedEntity,\n count: result.Success ? result.TotalRowCount : 0,\n isExpanded: false,\n records: [],\n isLoadingRecords: false,\n };\n });\n } catch (error) {\n console.warn('Failed to load organic key counts:', error);\n this.organicKeyMatches = allPairs.map(pair => ({\n organicKey: pair.organicKey,\n relatedEntity: pair.relatedEntity,\n relatedEntityName: pair.relatedEntity.DisplayName || pair.relatedEntity.RelatedEntity,\n count: 0,\n isExpanded: false,\n records: [],\n isLoadingRecords: false,\n }));\n } finally {\n this.ngZone.run(() => {\n this.isLoadingOrganicKeys = false;\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Get only organic key matches that have records (count > 0)\n */\n get organicKeyMatchesWithRecords(): OrganicKeyMatchData[] {\n return this.organicKeyMatches.filter(m => m.count > 0);\n }\n\n /**\n * Toggle expansion of an organic key match section and load records if needed\n */\n async toggleOrganicKeyExpansion(match: OrganicKeyMatchData, event: Event): Promise<void> {\n event.stopPropagation();\n if (match.count === 0) return;\n\n match.isExpanded = !match.isExpanded;\n\n if (match.isExpanded && match.records.length === 0 && !match.isLoadingRecords) {\n await this.loadOrganicKeyRecords(match);\n }\n }\n\n /**\n * Load actual records for an organic key match\n */\n private async loadOrganicKeyRecords(match: OrganicKeyMatchData): Promise<void> {\n if (!this.record || !this.entity) return;\n\n match.isLoadingRecords = true;\n this.cdr.detectChanges();\n\n const mockRecord = {\n Get: (fieldName: string) => this.record ? this.record[fieldName] ?? null : null,\n EntityInfo: this.entity,\n };\n\n try {\n const params = EntityInfo.BuildOrganicKeyViewParams(\n mockRecord as never,\n match.relatedEntity,\n match.organicKey,\n );\n\n const rv = new RunView();\n const relatedEntityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);\n const fields = relatedEntityInfo\n ? [...relatedEntityInfo.PrimaryKeys.map(pk => pk.Name),\n ...(relatedEntityInfo.NameField ? [relatedEntityInfo.NameField.Name] : []),\n ...relatedEntityInfo.Fields.filter(f => f.DefaultInView).map(f => f.Name)]\n : undefined;\n\n const result = await rv.RunView<Record<string, unknown>>({\n ...params,\n ResultType: 'simple',\n ...(fields ? { Fields: fields } : {}),\n MaxRows: 10,\n });\n\n if (result.Success) {\n match.records = result.Results;\n }\n } catch (error) {\n console.warn(`Failed to load organic key records for ${match.relatedEntityName}:`, error);\n } finally {\n this.ngZone.run(() => {\n match.isLoadingRecords = false;\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Handle click on an organic key record\n */\n onOrganicKeyRecordClick(match: OrganicKeyMatchData, record: Record<string, unknown>, event: Event): void {\n event.stopPropagation();\n this.openRelatedRecord.emit({\n entityName: match.relatedEntity.RelatedEntity,\n record,\n });\n }\n\n /**\n * Navigate to view all organic key matched records\n */\n onViewAllOrganicKey(match: OrganicKeyMatchData, event: Event): void {\n event.stopPropagation();\n if (!this.record || !this.entity) return;\n\n const mockRecord = {\n Get: (fieldName: string) => this.record ? this.record[fieldName] ?? null : null,\n EntityInfo: this.entity,\n };\n const params = EntityInfo.BuildOrganicKeyViewParams(\n mockRecord as never,\n match.relatedEntity,\n match.organicKey,\n );\n\n this.navigateToRelated.emit({\n entityName: match.relatedEntity.RelatedEntity,\n filter: String(params.ExtraFilter || ''),\n });\n }\n\n /**\n * Get display name for an organic key record\n */\n getOrganicKeyRecordDisplayName(match: OrganicKeyMatchData, record: Record<string, unknown>): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);\n if (entityInfo?.NameField) {\n const name = record[entityInfo.NameField.Name];\n if (name) return String(name);\n }\n if (entityInfo) {\n return buildPkString(record, entityInfo);\n }\n return 'Record';\n }\n\n /**\n * Get subtitle for an organic key record\n */\n getOrganicKeyRecordSubtitle(match: OrganicKeyMatchData, record: Record<string, unknown>): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);\n if (!entityInfo) return '';\n\n const subtitleFieldNames = ['Description', 'Status', 'Type', 'Email', 'Date', 'Amount', 'Total'];\n for (const fieldName of subtitleFieldNames) {\n const field = entityInfo.Fields.find(f =>\n f.Name.includes(fieldName) && f.Name !== entityInfo.NameField?.Name\n );\n if (field) {\n const value = record[field.Name];\n if (value !== null && value !== undefined) {\n return this.formatFieldValue(value, field.Name);\n }\n }\n }\n return '';\n }\n\n /**\n * Get icon for an organic key matched entity\n */\n getOrganicKeyEntityIcon(match: OrganicKeyMatchData): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === match.relatedEntity.RelatedEntity);\n if (entityInfo?.Icon) {\n return this.formatEntityIcon(entityInfo.Icon);\n }\n return 'fa-solid fa-link';\n }\n\n /**\n * Get key fields to display in details section, categorized by type\n */\n get displayFields(): FieldDisplay[] {\n if (!this.entity || !this.record) return [];\n\n const fields: FieldDisplay[] = [];\n const excludePatterns = ['__mj_', 'password', 'secret', 'token'];\n\n for (const field of this.entity.Fields) {\n // Skip system fields and sensitive fields\n if (excludePatterns.some(p => field.Name.toLowerCase().includes(p))) continue;\n // Skip very long text fields (but not FK fields which are usually GUIDs)\n if (field.Length && field.Length > 500 && !field.RelatedEntityID) continue;\n\n const value = this.record[field.Name];\n\n // Handle Primary Key fields specially\n if (field.IsPrimaryKey) {\n fields.push({\n type: 'primary-key',\n name: field.Name,\n label: this.formatFieldLabel(field),\n value: value !== null && value !== undefined ? String(value) : ''\n });\n continue;\n }\n\n // Handle Foreign Key fields - show the related record name instead of ID\n if (field.RelatedEntityID && field.RelatedEntityID.length > 0) {\n const fkDisplay = this.buildForeignKeyDisplay(field, value);\n if (fkDisplay) {\n fields.push(fkDisplay);\n }\n continue;\n }\n\n // Skip empty values for regular fields\n if (value === null || value === undefined || String(value).trim() === '') continue;\n\n // Limit regular fields to reasonable number\n if (fields.filter(f => f.type === 'regular' || f.type === 'enum').length >= 10) continue;\n\n // Check if this field has enumerated values\n const isEnum = field.ValueListTypeEnum !== EntityFieldValueListType.None &&\n field.EntityFieldValues.length > 0;\n\n fields.push({\n type: isEnum ? 'enum' : 'regular',\n name: field.Name,\n label: this.formatFieldLabel(field),\n value: this.formatFieldValue(value, field.Name)\n });\n }\n\n return fields;\n }\n\n /**\n * Build display info for a foreign key field\n * Uses RelatedEntityNameFieldMap to get the human-readable name\n * Label comes from the virtual field's DisplayNameOrName (e.g., \"Template\" not \"Template ID\")\n */\n private buildForeignKeyDisplay(field: EntityFieldInfo, value: unknown): FieldDisplay | null {\n if (value === null || value === undefined || String(value).trim() === '') {\n return null;\n }\n\n const fkValue = String(value);\n let displayValue = fkValue;\n let label = field.DisplayNameOrName; // Fallback to FK field's label\n\n // Try to get the display name from the mapped field\n // RelatedEntityNameFieldMap tells us which field contains the name of the related record\n if (field.RelatedEntityNameFieldMap && field.RelatedEntityNameFieldMap.trim().length > 0) {\n const mappedValue = this.record![field.RelatedEntityNameFieldMap];\n if (mappedValue !== null && mappedValue !== undefined && String(mappedValue).trim() !== '') {\n displayValue = String(mappedValue);\n }\n // Use the mapped field's DisplayNameOrName for the label\n const mappedField = this.entity!.Fields.find(f => f.Name === field.RelatedEntityNameFieldMap);\n if (mappedField) {\n label = mappedField.DisplayNameOrName;\n }\n } else {\n // Fallback: try to find a virtual field with the same name minus \"ID\" suffix\n // e.g., for \"TemplateID\", look for \"Template\" field\n const baseName = field.Name.replace(/ID$/i, '');\n if (baseName !== field.Name) {\n const virtualField = this.entity!.Fields.find(f =>\n f.Name.toLowerCase() === baseName.toLowerCase() && f.IsVirtual\n );\n if (virtualField) {\n const virtualValue = this.record![virtualField.Name];\n if (virtualValue !== null && virtualValue !== undefined && String(virtualValue).trim() !== '') {\n displayValue = String(virtualValue);\n }\n // Use the virtual field's DisplayNameOrName for the label\n label = virtualField.DisplayNameOrName;\n }\n }\n }\n\n return {\n type: 'foreign-key',\n name: field.Name,\n label: label,\n value: fkValue,\n displayValue: displayValue,\n relatedEntityName: field.RelatedEntity || undefined,\n relatedRecordId: fkValue\n };\n }\n\n /**\n * Format field name to display label using EntityFieldInfo's built-in property\n */\n private formatFieldLabel(field: EntityFieldInfo): string {\n return field.DisplayNameOrName;\n }\n\n /**\n * Format field value for display\n */\n private formatFieldValue(value: unknown, fieldName: string): string {\n if (value === null || value === undefined) return '-';\n\n // Handle dates\n if (value instanceof Date) {\n return value.toLocaleDateString();\n }\n\n // Handle booleans\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No';\n }\n\n // Handle numbers that look like currency\n if (typeof value === 'number') {\n const nameLower = fieldName.toLowerCase();\n if (nameLower.includes('amount') ||\n nameLower.includes('price') ||\n nameLower.includes('cost') ||\n nameLower.includes('total') ||\n nameLower.includes('value')) {\n return `$${value.toLocaleString()}`;\n }\n return value.toLocaleString();\n }\n\n const strValue = String(value);\n\n // Truncate long strings\n if (strValue.length > 100) {\n return strValue.substring(0, 100) + '...';\n }\n\n return strValue;\n }\n\n /**\n * Get record title\n */\n get recordTitle(): string {\n if (!this.entity || !this.record) return 'Record';\n\n if (this.entity.NameField) {\n const name = this.record[this.entity.NameField.Name];\n if (name) return String(name);\n }\n\n return buildPkString(this.record, this.entity);\n }\n\n /**\n * Handle close button click\n */\n onClose(): void {\n this.close.emit();\n }\n\n /**\n * Handle open record button click\n */\n onOpenRecord(): void {\n if (this.record) {\n this.openRecord.emit(this.record);\n }\n }\n\n /**\n * Copy primary key value to clipboard\n */\n copyToClipboard(value: string, event: Event): void {\n event.stopPropagation();\n navigator.clipboard.writeText(value).then(() => {\n // Could add a toast notification here\n console.log('Copied to clipboard:', value);\n }).catch(err => {\n console.error('Failed to copy:', err);\n });\n }\n\n /**\n * Open a foreign key record (FK link click)\n * Emits openForeignKeyRecord event for parent to handle opening the record\n */\n onForeignKeyClick(field: FieldDisplay, event: Event): void {\n event.stopPropagation();\n if (field.relatedEntityName && field.relatedRecordId) {\n this.openForeignKeyRecord.emit({\n entityName: field.relatedEntityName,\n recordId: field.relatedRecordId\n });\n }\n }\n\n /**\n * Check if a FK display value is different from the raw ID (i.e., we have a name to show)\n */\n hasFriendlyName(field: FieldDisplay): boolean {\n return field.type === 'foreign-key' &&\n field.displayValue !== undefined &&\n field.displayValue !== field.value;\n }\n\n /**\n * Toggle expansion of related entity section and load records if needed\n */\n async toggleRelatedEntityExpansion(relEntity: RelatedEntityData, event: Event): Promise<void> {\n event.stopPropagation();\n\n if (relEntity.count === 0) return;\n\n relEntity.isExpanded = !relEntity.isExpanded;\n\n // Load records on first expansion\n if (relEntity.isExpanded && relEntity.records.length === 0 && !relEntity.isLoadingRecords) {\n await this.loadRelatedRecords(relEntity);\n }\n }\n\n /**\n * Load actual records for a related entity\n */\n private async loadRelatedRecords(relEntity: RelatedEntityData): Promise<void> {\n if (!this.record || !this.entity) return;\n\n const compositeKey = buildCompositeKey(this.record, this.entity);\n const pkValue = compositeKey.KeyValuePairs[0]?.Value;\n if (!pkValue) return;\n\n relEntity.isLoadingRecords = true;\n this.cdr.detectChanges();\n\n try {\n const rv = new RunView();\n // Look up related entity info to compute fields\n const relatedEntityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relationship.RelatedEntity);\n const fields = relatedEntityInfo\n ? [...relatedEntityInfo.PrimaryKeys.map(pk => pk.Name),\n ...(relatedEntityInfo.NameField ? [relatedEntityInfo.NameField.Name] : []),\n ...relatedEntityInfo.Fields.filter(f => f.DefaultInView).map(f => f.Name)]\n : undefined;\n const result = await rv.RunView<Record<string, unknown>>({\n EntityName: relEntity.relationship.RelatedEntity,\n ExtraFilter: `${relEntity.relationship.RelatedEntityJoinField}='${pkValue}'`,\n ResultType: 'simple',\n ...(fields ? { Fields: fields } : {}),\n MaxRows: 10 // Limit inline display to 10 records\n });\n\n if (result.Success) {\n relEntity.records = result.Results;\n }\n } catch (error) {\n console.warn(`Failed to load records for ${relEntity.relatedEntityName}:`, error);\n } finally {\n this.ngZone.run(() => {\n relEntity.isLoadingRecords = false;\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Handle click on individual related record - opens in new tab\n */\n onRelatedRecordClick(relEntity: RelatedEntityData, record: Record<string, unknown>, event: Event): void {\n event.stopPropagation();\n this.openRelatedRecord.emit({\n entityName: relEntity.relatedEntityName,\n record\n });\n }\n\n /**\n * Navigate to view all related records (when count > 10)\n */\n onViewAllRelated(relEntity: RelatedEntityData, event: Event): void {\n event.stopPropagation();\n\n if (!this.record || !this.entity) return;\n\n const compositeKey = buildCompositeKey(this.record, this.entity);\n const pkValue = compositeKey.KeyValuePairs[0]?.Value;\n if (!pkValue) return;\n\n this.navigateToRelated.emit({\n entityName: relEntity.relatedEntityName,\n filter: `${relEntity.relationship.RelatedEntityJoinField}='${pkValue}'`\n });\n }\n\n /**\n * Get display name for a related record\n */\n getRelatedRecordDisplayName(relEntity: RelatedEntityData, record: Record<string, unknown>): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relatedEntityName);\n if (entityInfo?.NameField) {\n const name = record[entityInfo.NameField.Name];\n if (name) return String(name);\n }\n if (entityInfo) {\n return buildPkString(record, entityInfo);\n }\n return 'Record';\n }\n\n /**\n * Get subtitle/secondary info for a related record\n */\n getRelatedRecordSubtitle(relEntity: RelatedEntityData, record: Record<string, unknown>): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relatedEntityName);\n if (!entityInfo) return '';\n\n // Look for common subtitle fields\n const subtitleFieldNames = ['Description', 'Status', 'Type', 'Email', 'Date', 'Amount', 'Total'];\n for (const fieldName of subtitleFieldNames) {\n const field = entityInfo.Fields.find(f =>\n f.Name.includes(fieldName) && f.Name !== entityInfo.NameField?.Name\n );\n if (field) {\n const value = record[field.Name];\n if (value !== null && value !== undefined) {\n return this.formatFieldValue(value, field.Name);\n }\n }\n }\n return '';\n }\n\n /**\n * Toggle section expansion\n */\n toggleSection(section: 'details' | 'relationships' | 'organicKeys'): void {\n if (section === 'details') {\n this.detailsSectionExpanded = !this.detailsSectionExpanded;\n } else if (section === 'relationships') {\n this.relationshipsSectionExpanded = !this.relationshipsSectionExpanded;\n } else {\n this.organicKeysSectionExpanded = !this.organicKeysSectionExpanded;\n }\n }\n\n /**\n * Get only related entities that have records (count > 0)\n */\n get relatedEntitiesWithRecords(): RelatedEntityData[] {\n return this.relatedEntities.filter(r => r.count > 0);\n }\n\n /**\n * Get icon for related entity by looking up EntityInfo from Metadata\n */\n getRelatedEntityIcon(relEntity: RelatedEntityData): string {\n const entityInfo = this.metadata.Entities.find(e => e.Name === relEntity.relatedEntityName);\n if (entityInfo?.Icon) {\n return this.formatEntityIcon(entityInfo.Icon);\n }\n return 'fa-solid fa-table';\n }\n\n /**\n * Get the icon class for the current entity\n */\n getEntityIconClass(): string {\n if (!this.entity?.Icon) {\n return 'fa-solid fa-table';\n }\n return this.formatEntityIcon(this.entity.Icon);\n }\n\n /**\n * Format entity icon to ensure proper Font Awesome class format\n */\n private formatEntityIcon(icon: string): string {\n if (!icon) {\n return 'fa-solid fa-table';\n }\n // If icon already has fa- prefix, use it as-is\n if (icon.startsWith('fa-') || icon.startsWith('fa ')) {\n // Ensure it has a style prefix (fa-solid, fa-regular, etc.)\n if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||\n icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||\n icon.startsWith('fa ')) {\n return icon;\n }\n // It's just \"fa-something\", add fa-solid prefix\n return `fa-solid ${icon}`;\n }\n // Check if it's just an icon name like \"table\" or \"users\"\n return `fa-solid fa-${icon}`;\n }\n}\n","<div class=\"entity-record-card-container\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title-row\">\n @if (entity?.Icon) {\n <i [class]=\"getEntityIconClass()\" class=\"entity-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ recordTitle }}</h3>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Details Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('details')\">\n <i class=\"fa-solid fa-info-circle section-icon\"></i>\n <span class=\"section-title\">Details</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"detailsSectionExpanded\" [class.fa-chevron-right]=\"!detailsSectionExpanded\"></i>\n </div>\n\n @if (detailsSectionExpanded) {\n <div class=\"section-content\">\n @for (field of displayFields; track field.name) {\n <!-- Primary Key Field - Compact with copy button -->\n @if (field.type === 'primary-key') {\n <div class=\"field-row field-row-pk\">\n <div class=\"pk-row\">\n <i class=\"fa-solid fa-key pk-icon\"></i>\n <span class=\"field-label\">{{ field.label }}</span>\n <button class=\"copy-btn\" (click)=\"copyToClipboard(field.value, $event)\" title=\"Copy ID\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n </div>\n }\n <!-- Foreign Key Field - Show friendly name with open button -->\n @else if (field.type === 'foreign-key') {\n <div class=\"field-row field-row-fk\">\n <span class=\"field-label\">{{ field.label }}</span>\n <div class=\"fk-value-row\" [class.fk-id-only]=\"!hasFriendlyName(field)\">\n @if (hasFriendlyName(field)) {\n <span class=\"field-value fk-display-value\">{{ field.displayValue }}</span>\n } @else {\n <!-- No friendly name available, show ID in muted style -->\n <span class=\"field-value fk-id-value\">{{ field.value }}</span>\n }\n <!-- Always show open button for FK fields that have a related entity -->\n @if (field.relatedEntityName) {\n <button class=\"fk-link-btn\" (click)=\"onForeignKeyClick(field, $event)\" title=\"Open {{ field.relatedEntityName }} record\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n </div>\n </div>\n }\n <!-- Enum Field - Show as pill -->\n @else if (field.type === 'enum') {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <mj-pill [value]=\"field.value\"></mj-pill>\n </div>\n }\n <!-- Regular Field -->\n @else {\n <div class=\"field-row\">\n <span class=\"field-label\">{{ field.label }}</span>\n <span class=\"field-value\">{{ field.value }}</span>\n </div>\n }\n }\n\n @if (displayFields.length === 0) {\n <div class=\"empty-section\">No details available</div>\n }\n </div>\n }\n </div>\n\n <!-- Relationships Section -->\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('relationships')\">\n <i class=\"fa-solid fa-project-diagram section-icon\"></i>\n <span class=\"section-title\">Related Records</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"relationshipsSectionExpanded\" [class.fa-chevron-right]=\"!relationshipsSectionExpanded\"></i>\n </div>\n\n @if (relationshipsSectionExpanded) {\n <div class=\"section-content\">\n @if (isLoadingRelationships) {\n <div class=\"relationships-loading\">\n <mj-loading text=\"Loading related records...\" size=\"small\"></mj-loading>\n </div>\n } @else if (relatedEntitiesWithRecords.length === 0) {\n <div class=\"empty-section\">No related records</div>\n } @else {\n @for (relEntity of relatedEntitiesWithRecords; track relEntity.relatedEntityName) {\n <div class=\"related-entity-group\" [class.expanded]=\"relEntity.isExpanded\">\n <!-- Header row - click to expand -->\n <div\n class=\"related-entity-header\"\n [class.clickable]=\"relEntity.count > 0\"\n (click)=\"toggleRelatedEntityExpansion(relEntity, $event)\">\n <i class=\"fa-solid expand-chevron\"\n [class.fa-chevron-down]=\"relEntity.isExpanded\"\n [class.fa-chevron-right]=\"!relEntity.isExpanded\"></i>\n <i [class]=\"getRelatedEntityIcon(relEntity)\"></i>\n <span class=\"related-entity-name\">{{ relEntity.relatedEntityName }}</span>\n <span class=\"related-entity-count\">{{ relEntity.count }}</span>\n </div>\n\n <!-- Expanded records list -->\n @if (relEntity.isExpanded) {\n <div class=\"related-records-list\">\n @if (relEntity.isLoadingRecords) {\n <div class=\"records-loading\">\n <mj-loading text=\"Loading...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n @for (rec of relEntity.records; track $index) {\n <div class=\"related-record-item\" (click)=\"onRelatedRecordClick(relEntity, rec, $event)\">\n <div class=\"record-info\">\n <span class=\"record-name\">{{ getRelatedRecordDisplayName(relEntity, rec) }}</span>\n @if (getRelatedRecordSubtitle(relEntity, rec); as subtitle) {\n <span class=\"record-subtitle\">{{ subtitle }}</span>\n }\n </div>\n <i class=\"fa-solid fa-external-link-alt record-open-icon\"></i>\n </div>\n }\n\n <!-- View All link if there are more records -->\n @if (relEntity.count > 10) {\n <div class=\"view-all-link\" (click)=\"onViewAllRelated(relEntity, $event)\">\n <span>View all {{ relEntity.count }} records</span>\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n\n <!-- Organic Key Matches Section -->\n @if (organicKeyMatches.length > 0 || isLoadingOrganicKeys) {\n <div class=\"section\">\n <div class=\"section-header\" (click)=\"toggleSection('organicKeys')\">\n <i class=\"fa-solid fa-link section-icon\"></i>\n <span class=\"section-title\">Organic Key Matches</span>\n <i class=\"fa-solid expand-icon\" [class.fa-chevron-down]=\"organicKeysSectionExpanded\" [class.fa-chevron-right]=\"!organicKeysSectionExpanded\"></i>\n </div>\n\n @if (organicKeysSectionExpanded) {\n <div class=\"section-content\">\n @if (isLoadingOrganicKeys) {\n <div class=\"relationships-loading\">\n <mj-loading text=\"Loading organic key matches...\" size=\"small\"></mj-loading>\n </div>\n } @else if (organicKeyMatchesWithRecords.length === 0) {\n <div class=\"empty-section\">No organic key matches</div>\n } @else {\n @for (match of organicKeyMatchesWithRecords; track match.relatedEntityName) {\n <div class=\"related-entity-group\" [class.expanded]=\"match.isExpanded\">\n <div\n class=\"related-entity-header\"\n [class.clickable]=\"match.count > 0\"\n (click)=\"toggleOrganicKeyExpansion(match, $event)\">\n <i class=\"fa-solid expand-chevron\"\n [class.fa-chevron-down]=\"match.isExpanded\"\n [class.fa-chevron-right]=\"!match.isExpanded\"></i>\n <i [class]=\"getOrganicKeyEntityIcon(match)\"></i>\n <span class=\"related-entity-name\">{{ match.relatedEntityName }}</span>\n <span class=\"related-entity-count\">{{ match.count }}</span>\n </div>\n\n @if (match.isExpanded) {\n <div class=\"related-records-list\">\n @if (match.isLoadingRecords) {\n <div class=\"records-loading\">\n <mj-loading text=\"Loading...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n @for (rec of match.records; track $index) {\n <div class=\"related-record-item\" (click)=\"onOrganicKeyRecordClick(match, rec, $event)\">\n <div class=\"record-info\">\n <span class=\"record-name\">{{ getOrganicKeyRecordDisplayName(match, rec) }}</span>\n @if (getOrganicKeyRecordSubtitle(match, rec); as subtitle) {\n <span class=\"record-subtitle\">{{ subtitle }}</span>\n }\n </div>\n <i class=\"fa-solid fa-external-link-alt record-open-icon\"></i>\n </div>\n }\n\n @if (match.count > 10) {\n <div class=\"view-all-link\" (click)=\"onViewAllOrganicKey(match, $event)\">\n <span>View all {{ match.count }} records</span>\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"open-record-btn\" (click)=\"onOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n </div>\n</div>\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-entity-viewer",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.15.0",
|
|
4
4
|
"description": "MemberJunction: Angular components for viewing entity data in multiple formats (grid, cards) with filtering, selection, and shared data management",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"ag-grid-community": "^35.0.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@memberjunction/core-entities": "5.
|
|
41
|
-
"@memberjunction/export-engine": "5.
|
|
42
|
-
"@memberjunction/global": "5.
|
|
43
|
-
"@memberjunction/core": "5.
|
|
44
|
-
"@memberjunction/ng-pagination": "5.
|
|
45
|
-
"@memberjunction/ng-shared-generic": "5.
|
|
46
|
-
"@memberjunction/ng-timeline": "5.
|
|
47
|
-
"@memberjunction/ng-filter-builder": "5.
|
|
48
|
-
"@memberjunction/ng-export-service": "5.
|
|
40
|
+
"@memberjunction/core-entities": "5.15.0",
|
|
41
|
+
"@memberjunction/export-engine": "5.15.0",
|
|
42
|
+
"@memberjunction/global": "5.15.0",
|
|
43
|
+
"@memberjunction/core": "5.15.0",
|
|
44
|
+
"@memberjunction/ng-pagination": "5.15.0",
|
|
45
|
+
"@memberjunction/ng-shared-generic": "5.15.0",
|
|
46
|
+
"@memberjunction/ng-timeline": "5.15.0",
|
|
47
|
+
"@memberjunction/ng-filter-builder": "5.15.0",
|
|
48
|
+
"@memberjunction/ng-export-service": "5.15.0",
|
|
49
49
|
"rxjs": "^7.8.2",
|
|
50
50
|
"tslib": "^2.8.1"
|
|
51
51
|
},
|