@memberjunction/ng-entity-viewer 0.0.1 → 2.121.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +224 -43
- package/dist/lib/entity-cards/entity-cards.component.d.ts +163 -0
- package/dist/lib/entity-cards/entity-cards.component.d.ts.map +1 -0
- package/dist/lib/entity-cards/entity-cards.component.js +797 -0
- package/dist/lib/entity-cards/entity-cards.component.js.map +1 -0
- package/dist/lib/entity-grid/entity-grid.component.d.ts +216 -0
- package/dist/lib/entity-grid/entity-grid.component.d.ts.map +1 -0
- package/dist/lib/entity-grid/entity-grid.component.js +676 -0
- package/dist/lib/entity-grid/entity-grid.component.js.map +1 -0
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts +182 -0
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts.map +1 -0
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js +787 -0
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js.map +1 -0
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts +252 -0
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts.map +1 -0
- package/dist/lib/entity-viewer/entity-viewer.component.js +883 -0
- package/dist/lib/entity-viewer/entity-viewer.component.js.map +1 -0
- package/dist/lib/pagination/pagination.component.d.ts +60 -0
- package/dist/lib/pagination/pagination.component.d.ts.map +1 -0
- package/dist/lib/pagination/pagination.component.js +199 -0
- package/dist/lib/pagination/pagination.component.js.map +1 -0
- package/dist/lib/pill/pill.component.d.ts +58 -0
- package/dist/lib/pill/pill.component.d.ts.map +1 -0
- package/dist/lib/pill/pill.component.js +125 -0
- package/dist/lib/pill/pill.component.js.map +1 -0
- package/dist/lib/types.d.ts +316 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +30 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils/highlight.util.d.ts +69 -0
- package/dist/lib/utils/highlight.util.d.ts.map +1 -0
- package/dist/lib/utils/highlight.util.js +214 -0
- package/dist/lib/utils/highlight.util.js.map +1 -0
- package/dist/module.d.ts +38 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +83 -0
- package/dist/module.js.map +1 -0
- package/dist/public-api.d.ts +16 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +20 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +45 -6
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { EntityFieldValueListType, RunView } from '@memberjunction/core';
|
|
3
|
+
import { PillColorUtil } from '../pill/pill.component';
|
|
4
|
+
import { HighlightUtil } from '../utils/highlight.util';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@memberjunction/ng-shared-generic";
|
|
7
|
+
import * as i2 from "../pill/pill.component";
|
|
8
|
+
function _forTrack0($index, $item) { return this.getRecordTrackId($item, $index); }
|
|
9
|
+
const _forTrack1 = ($index, $item) => $item.name;
|
|
10
|
+
function EntityCardsComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
11
|
+
i0.ɵɵelementStart(0, "div", 1);
|
|
12
|
+
i0.ɵɵelement(1, "mj-loading", 3);
|
|
13
|
+
i0.ɵɵelementEnd();
|
|
14
|
+
} }
|
|
15
|
+
function EntityCardsComponent_Conditional_2_For_2_Case_2_Template(rf, ctx) { if (rf & 1) {
|
|
16
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
17
|
+
i0.ɵɵelement(1, "img", 19);
|
|
18
|
+
i0.ɵɵelementEnd();
|
|
19
|
+
} if (rf & 2) {
|
|
20
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
21
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
22
|
+
i0.ɵɵadvance();
|
|
23
|
+
i0.ɵɵproperty("src", ctx_r2.getThumbnailUrl(record_r2), i0.ɵɵsanitizeUrl);
|
|
24
|
+
} }
|
|
25
|
+
function EntityCardsComponent_Conditional_2_For_2_Case_3_Template(rf, ctx) { if (rf & 1) {
|
|
26
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
27
|
+
i0.ɵɵelement(1, "i");
|
|
28
|
+
i0.ɵɵelementEnd();
|
|
29
|
+
} if (rf & 2) {
|
|
30
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
31
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
32
|
+
i0.ɵɵstyleProp("background-color", ctx_r2.getRecordColor(record_r2));
|
|
33
|
+
i0.ɵɵadvance();
|
|
34
|
+
i0.ɵɵclassMap(ctx_r2.getThumbnailUrl(record_r2));
|
|
35
|
+
} }
|
|
36
|
+
function EntityCardsComponent_Conditional_2_For_2_Case_4_Template(rf, ctx) { if (rf & 1) {
|
|
37
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
38
|
+
i0.ɵɵtext(1);
|
|
39
|
+
i0.ɵɵelementEnd();
|
|
40
|
+
} if (rf & 2) {
|
|
41
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
42
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
43
|
+
i0.ɵɵstyleProp("background-color", ctx_r2.getRecordColor(record_r2));
|
|
44
|
+
i0.ɵɵadvance();
|
|
45
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.getInitials(record_r2), " ");
|
|
46
|
+
} }
|
|
47
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_7_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
48
|
+
i0.ɵɵelement(0, "mj-pill", 21);
|
|
49
|
+
} if (rf & 2) {
|
|
50
|
+
const subField_r4 = i0.ɵɵnextContext();
|
|
51
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
52
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
53
|
+
i0.ɵɵproperty("value", ctx_r2.getFieldValue(record_r2, subField_r4));
|
|
54
|
+
} }
|
|
55
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelement(0, "span", 22);
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
const subField_r4 = i0.ɵɵnextContext();
|
|
59
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
60
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
61
|
+
i0.ɵɵproperty("innerHTML", ctx_r2.highlightMatch(ctx_r2.getFieldValue(record_r2, subField_r4)), i0.ɵɵsanitizeHtml);
|
|
62
|
+
} }
|
|
63
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
64
|
+
i0.ɵɵtemplate(0, EntityCardsComponent_Conditional_2_For_2_Conditional_7_Conditional_0_Template, 1, 1, "mj-pill", 21)(1, EntityCardsComponent_Conditional_2_For_2_Conditional_7_Conditional_1_Template, 1, 1, "span", 22);
|
|
65
|
+
} if (rf & 2) {
|
|
66
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
67
|
+
i0.ɵɵconditional(ctx_r2.subtitleIsPill ? 0 : 1);
|
|
68
|
+
} }
|
|
69
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
70
|
+
i0.ɵɵelement(0, "p", 15);
|
|
71
|
+
} if (rf & 2) {
|
|
72
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
73
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
74
|
+
i0.ɵɵproperty("innerHTML", ctx_r2.highlightMatch(ctx_r2.getTextValue(record_r2, ctx, 100)), i0.ɵɵsanitizeHtml);
|
|
75
|
+
} }
|
|
76
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_1_Template(rf, ctx) { if (rf & 1) {
|
|
77
|
+
i0.ɵɵelement(0, "i", 25);
|
|
78
|
+
i0.ɵɵelementStart(1, "span", 26);
|
|
79
|
+
i0.ɵɵtext(2);
|
|
80
|
+
i0.ɵɵelementEnd();
|
|
81
|
+
} if (rf & 2) {
|
|
82
|
+
const field_r5 = i0.ɵɵnextContext().$implicit;
|
|
83
|
+
const record_r2 = i0.ɵɵnextContext(2).$implicit;
|
|
84
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
85
|
+
i0.ɵɵclassProp("fa-solid", true)("fa-check", ctx_r2.getBooleanValue(record_r2, field_r5.name))("fa-minus", !ctx_r2.getBooleanValue(record_r2, field_r5.name))("bool-true", ctx_r2.getBooleanValue(record_r2, field_r5.name))("bool-false", !ctx_r2.getBooleanValue(record_r2, field_r5.name));
|
|
86
|
+
i0.ɵɵadvance(2);
|
|
87
|
+
i0.ɵɵtextInterpolate(field_r5.label);
|
|
88
|
+
} }
|
|
89
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_2_Template(rf, ctx) { if (rf & 1) {
|
|
90
|
+
i0.ɵɵelementStart(0, "span", 27);
|
|
91
|
+
i0.ɵɵtext(1);
|
|
92
|
+
i0.ɵɵelementEnd();
|
|
93
|
+
i0.ɵɵelementStart(2, "span", 26);
|
|
94
|
+
i0.ɵɵtext(3);
|
|
95
|
+
i0.ɵɵelementEnd();
|
|
96
|
+
} if (rf & 2) {
|
|
97
|
+
const field_r5 = i0.ɵɵnextContext().$implicit;
|
|
98
|
+
const record_r2 = i0.ɵɵnextContext(2).$implicit;
|
|
99
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
100
|
+
i0.ɵɵadvance();
|
|
101
|
+
i0.ɵɵtextInterpolate(ctx_r2.getNumericValue(record_r2, field_r5.name));
|
|
102
|
+
i0.ɵɵadvance(2);
|
|
103
|
+
i0.ɵɵtextInterpolate(field_r5.label);
|
|
104
|
+
} }
|
|
105
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_3_Template(rf, ctx) { if (rf & 1) {
|
|
106
|
+
i0.ɵɵelementStart(0, "span", 28);
|
|
107
|
+
i0.ɵɵtext(1);
|
|
108
|
+
i0.ɵɵelementEnd();
|
|
109
|
+
i0.ɵɵelementStart(2, "span", 26);
|
|
110
|
+
i0.ɵɵtext(3);
|
|
111
|
+
i0.ɵɵelementEnd();
|
|
112
|
+
} if (rf & 2) {
|
|
113
|
+
const field_r5 = i0.ɵɵnextContext().$implicit;
|
|
114
|
+
const record_r2 = i0.ɵɵnextContext(2).$implicit;
|
|
115
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
116
|
+
i0.ɵɵadvance();
|
|
117
|
+
i0.ɵɵtextInterpolate(ctx_r2.getDateValue(record_r2, field_r5.name));
|
|
118
|
+
i0.ɵɵadvance(2);
|
|
119
|
+
i0.ɵɵtextInterpolate(field_r5.label);
|
|
120
|
+
} }
|
|
121
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_4_Template(rf, ctx) { if (rf & 1) {
|
|
122
|
+
i0.ɵɵelementStart(0, "span", 26);
|
|
123
|
+
i0.ɵɵtext(1);
|
|
124
|
+
i0.ɵɵelementEnd();
|
|
125
|
+
i0.ɵɵelement(2, "span", 29);
|
|
126
|
+
} if (rf & 2) {
|
|
127
|
+
const field_r5 = i0.ɵɵnextContext().$implicit;
|
|
128
|
+
const record_r2 = i0.ɵɵnextContext(2).$implicit;
|
|
129
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
130
|
+
i0.ɵɵadvance();
|
|
131
|
+
i0.ɵɵtextInterpolate(field_r5.label);
|
|
132
|
+
i0.ɵɵadvance();
|
|
133
|
+
i0.ɵɵproperty("innerHTML", ctx_r2.highlightMatch(ctx_r2.getTextValue(record_r2, field_r5.name, 40)), i0.ɵɵsanitizeHtml);
|
|
134
|
+
} }
|
|
135
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
136
|
+
i0.ɵɵelementStart(0, "div", 24);
|
|
137
|
+
i0.ɵɵtemplate(1, EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_1_Template, 3, 11)(2, EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_2_Template, 4, 2)(3, EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_3_Template, 4, 2)(4, EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Case_4_Template, 3, 2);
|
|
138
|
+
i0.ɵɵelementEnd();
|
|
139
|
+
} if (rf & 2) {
|
|
140
|
+
let tmp_24_0;
|
|
141
|
+
const field_r5 = ctx.$implicit;
|
|
142
|
+
i0.ɵɵclassProp("field-boolean", field_r5.type === "boolean")("field-text", field_r5.type === "text");
|
|
143
|
+
i0.ɵɵadvance();
|
|
144
|
+
i0.ɵɵconditional((tmp_24_0 = field_r5.type) === "boolean" ? 1 : tmp_24_0 === "number" ? 2 : tmp_24_0 === "date" ? 3 : 4);
|
|
145
|
+
} }
|
|
146
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
147
|
+
i0.ɵɵelementStart(0, "div", 16);
|
|
148
|
+
i0.ɵɵrepeaterCreate(1, EntityCardsComponent_Conditional_2_For_2_Conditional_12_For_2_Template, 5, 5, "div", 23, _forTrack1);
|
|
149
|
+
i0.ɵɵelementEnd();
|
|
150
|
+
} if (rf & 2) {
|
|
151
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
152
|
+
i0.ɵɵadvance();
|
|
153
|
+
i0.ɵɵrepeater(ctx_r2.effectiveTemplate.displayFields);
|
|
154
|
+
} }
|
|
155
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
156
|
+
i0.ɵɵelementStart(0, "div", 17);
|
|
157
|
+
i0.ɵɵelement(1, "mj-pill", 21);
|
|
158
|
+
i0.ɵɵelementEnd();
|
|
159
|
+
} if (rf & 2) {
|
|
160
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
161
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
162
|
+
i0.ɵɵadvance();
|
|
163
|
+
i0.ɵɵproperty("value", ctx_r2.getFieldValue(record_r2, ctx));
|
|
164
|
+
} }
|
|
165
|
+
function EntityCardsComponent_Conditional_2_For_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
166
|
+
i0.ɵɵelementStart(0, "div", 18);
|
|
167
|
+
i0.ɵɵelement(1, "i", 30);
|
|
168
|
+
i0.ɵɵelementStart(2, "span");
|
|
169
|
+
i0.ɵɵtext(3);
|
|
170
|
+
i0.ɵɵelementEnd()();
|
|
171
|
+
} if (rf & 2) {
|
|
172
|
+
const record_r2 = i0.ɵɵnextContext().$implicit;
|
|
173
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
174
|
+
i0.ɵɵproperty("title", "Matched in: " + ctx_r2.getHiddenMatchFieldName(record_r2));
|
|
175
|
+
i0.ɵɵadvance(3);
|
|
176
|
+
i0.ɵɵtextInterpolate(ctx_r2.getHiddenMatchFieldName(record_r2));
|
|
177
|
+
} }
|
|
178
|
+
function EntityCardsComponent_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
179
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
180
|
+
i0.ɵɵelementStart(0, "div", 6);
|
|
181
|
+
i0.ɵɵlistener("click", function EntityCardsComponent_Conditional_2_For_2_Template_div_click_0_listener() { const record_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onCardClick(record_r2)); });
|
|
182
|
+
i0.ɵɵelementStart(1, "div", 7);
|
|
183
|
+
i0.ɵɵtemplate(2, EntityCardsComponent_Conditional_2_For_2_Case_2_Template, 2, 1, "div", 8)(3, EntityCardsComponent_Conditional_2_For_2_Case_3_Template, 2, 4, "div", 9)(4, EntityCardsComponent_Conditional_2_For_2_Case_4_Template, 2, 3, "div", 9);
|
|
184
|
+
i0.ɵɵelementStart(5, "div", 10);
|
|
185
|
+
i0.ɵɵelement(6, "h3", 11);
|
|
186
|
+
i0.ɵɵtemplate(7, EntityCardsComponent_Conditional_2_For_2_Conditional_7_Template, 2, 1);
|
|
187
|
+
i0.ɵɵelementEnd();
|
|
188
|
+
i0.ɵɵelementStart(8, "button", 12);
|
|
189
|
+
i0.ɵɵlistener("click", function EntityCardsComponent_Conditional_2_For_2_Template_button_click_8_listener($event) { const record_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onOpenClick($event, record_r2)); });
|
|
190
|
+
i0.ɵɵelement(9, "i", 13);
|
|
191
|
+
i0.ɵɵelementEnd()();
|
|
192
|
+
i0.ɵɵelementStart(10, "div", 14);
|
|
193
|
+
i0.ɵɵtemplate(11, EntityCardsComponent_Conditional_2_For_2_Conditional_11_Template, 1, 1, "p", 15)(12, EntityCardsComponent_Conditional_2_For_2_Conditional_12_Template, 3, 0, "div", 16);
|
|
194
|
+
i0.ɵɵelementEnd();
|
|
195
|
+
i0.ɵɵtemplate(13, EntityCardsComponent_Conditional_2_For_2_Conditional_13_Template, 2, 1, "div", 17)(14, EntityCardsComponent_Conditional_2_For_2_Conditional_14_Template, 4, 2, "div", 18);
|
|
196
|
+
i0.ɵɵelementEnd();
|
|
197
|
+
} if (rf & 2) {
|
|
198
|
+
let tmp_12_0;
|
|
199
|
+
let tmp_13_0;
|
|
200
|
+
let tmp_14_0;
|
|
201
|
+
let tmp_15_0;
|
|
202
|
+
let tmp_17_0;
|
|
203
|
+
const record_r2 = ctx.$implicit;
|
|
204
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
205
|
+
i0.ɵɵclassProp("selected", ctx_r2.isSelected(record_r2));
|
|
206
|
+
i0.ɵɵadvance(2);
|
|
207
|
+
i0.ɵɵconditional((tmp_12_0 = ctx_r2.getThumbnailType(record_r2)) === "image" ? 2 : tmp_12_0 === "icon" ? 3 : 4);
|
|
208
|
+
i0.ɵɵadvance(4);
|
|
209
|
+
i0.ɵɵproperty("innerHTML", ctx_r2.highlightMatch(ctx_r2.getFieldValue(record_r2, (tmp_13_0 = ctx_r2.effectiveTemplate == null ? null : ctx_r2.effectiveTemplate.titleField) !== null && tmp_13_0 !== undefined ? tmp_13_0 : null)), i0.ɵɵsanitizeHtml);
|
|
210
|
+
i0.ɵɵadvance();
|
|
211
|
+
i0.ɵɵconditional((tmp_14_0 = ctx_r2.effectiveTemplate == null ? null : ctx_r2.effectiveTemplate.subtitleField) ? 7 : -1, tmp_14_0);
|
|
212
|
+
i0.ɵɵadvance(4);
|
|
213
|
+
i0.ɵɵconditional((tmp_15_0 = ctx_r2.effectiveTemplate == null ? null : ctx_r2.effectiveTemplate.descriptionField) ? 11 : -1, tmp_15_0);
|
|
214
|
+
i0.ɵɵadvance();
|
|
215
|
+
i0.ɵɵconditional(ctx_r2.effectiveTemplate && ctx_r2.effectiveTemplate.displayFields.length > 0 ? 12 : -1);
|
|
216
|
+
i0.ɵɵadvance();
|
|
217
|
+
i0.ɵɵconditional((tmp_17_0 = ctx_r2.effectiveTemplate == null ? null : ctx_r2.effectiveTemplate.badgeField) ? 13 : -1, tmp_17_0);
|
|
218
|
+
i0.ɵɵadvance();
|
|
219
|
+
i0.ɵɵconditional(ctx_r2.hasHiddenFieldMatch(record_r2) ? 14 : -1);
|
|
220
|
+
} }
|
|
221
|
+
function EntityCardsComponent_Conditional_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
222
|
+
i0.ɵɵelementStart(0, "div", 5);
|
|
223
|
+
i0.ɵɵelement(1, "i", 31);
|
|
224
|
+
i0.ɵɵelementStart(2, "p");
|
|
225
|
+
i0.ɵɵtext(3, "No records to display");
|
|
226
|
+
i0.ɵɵelementEnd()();
|
|
227
|
+
} }
|
|
228
|
+
function EntityCardsComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
229
|
+
i0.ɵɵelementStart(0, "div", 2);
|
|
230
|
+
i0.ɵɵrepeaterCreate(1, EntityCardsComponent_Conditional_2_For_2_Template, 15, 9, "div", 4, _forTrack0, true);
|
|
231
|
+
i0.ɵɵtemplate(3, EntityCardsComponent_Conditional_2_Conditional_3_Template, 4, 0, "div", 5);
|
|
232
|
+
i0.ɵɵelementEnd();
|
|
233
|
+
} if (rf & 2) {
|
|
234
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
235
|
+
i0.ɵɵadvance();
|
|
236
|
+
i0.ɵɵrepeater(ctx_r2.effectiveRecords);
|
|
237
|
+
i0.ɵɵadvance(2);
|
|
238
|
+
i0.ɵɵconditional(ctx_r2.effectiveRecords.length === 0 ? 3 : -1);
|
|
239
|
+
} }
|
|
240
|
+
/**
|
|
241
|
+
* EntityCardsComponent - Card-based view for entity records
|
|
242
|
+
*
|
|
243
|
+
* This component provides an auto-generated card layout for displaying
|
|
244
|
+
* entity records. Cards are automatically structured based on entity metadata.
|
|
245
|
+
*
|
|
246
|
+
* Supports two modes:
|
|
247
|
+
* 1. Parent-managed data: Records are passed in via [records] input
|
|
248
|
+
* 2. Standalone: Component loads its own data with pagination
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```html
|
|
252
|
+
* <mj-entity-cards
|
|
253
|
+
* [entity]="selectedEntity"
|
|
254
|
+
* [records]="filteredRecords"
|
|
255
|
+
* [selectedRecordId]="selectedId"
|
|
256
|
+
* (recordSelected)="onRecordSelected($event)"
|
|
257
|
+
* (recordOpened)="onRecordOpened($event)">
|
|
258
|
+
* </mj-entity-cards>
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export class EntityCardsComponent {
|
|
262
|
+
elementRef;
|
|
263
|
+
cdr;
|
|
264
|
+
constructor(elementRef, cdr) {
|
|
265
|
+
this.elementRef = elementRef;
|
|
266
|
+
this.cdr = cdr;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* The entity metadata for the records being displayed
|
|
270
|
+
*/
|
|
271
|
+
entity = null;
|
|
272
|
+
/**
|
|
273
|
+
* The records to display as cards (optional - component can load its own)
|
|
274
|
+
*/
|
|
275
|
+
records = null;
|
|
276
|
+
/**
|
|
277
|
+
* The currently selected record's primary key string
|
|
278
|
+
*/
|
|
279
|
+
selectedRecordId = null;
|
|
280
|
+
/**
|
|
281
|
+
* Custom card template (optional - auto-generated if not provided)
|
|
282
|
+
*/
|
|
283
|
+
cardTemplate = null;
|
|
284
|
+
/**
|
|
285
|
+
* Map of record IDs to hidden field names that matched the filter
|
|
286
|
+
* Used to display an indicator when a match occurred in a non-visible field
|
|
287
|
+
*/
|
|
288
|
+
hiddenFieldMatches = new Map();
|
|
289
|
+
/**
|
|
290
|
+
* Current filter text for highlighting matches
|
|
291
|
+
* Supports SQL-style % wildcards
|
|
292
|
+
*/
|
|
293
|
+
filterText = '';
|
|
294
|
+
/**
|
|
295
|
+
* Page size for standalone data loading
|
|
296
|
+
* @default 100
|
|
297
|
+
*/
|
|
298
|
+
pageSize = 100;
|
|
299
|
+
/**
|
|
300
|
+
* Emitted when a record is selected (single click)
|
|
301
|
+
*/
|
|
302
|
+
recordSelected = new EventEmitter();
|
|
303
|
+
/**
|
|
304
|
+
* Emitted when a record should be opened (double click or open button)
|
|
305
|
+
*/
|
|
306
|
+
recordOpened = new EventEmitter();
|
|
307
|
+
/** Auto-generated card template */
|
|
308
|
+
autoCardTemplate = null;
|
|
309
|
+
/** Internal records when loading standalone */
|
|
310
|
+
internalRecords = [];
|
|
311
|
+
/** Track if we're in standalone mode */
|
|
312
|
+
standaloneMode = false;
|
|
313
|
+
/** Loading state for standalone mode */
|
|
314
|
+
isLoading = false;
|
|
315
|
+
/** Flag to trigger scroll to selected card after view renders */
|
|
316
|
+
pendingScrollToSelected = false;
|
|
317
|
+
ngOnInit() {
|
|
318
|
+
this.standaloneMode = this.records === null;
|
|
319
|
+
if (this.entity?.Fields && !this.effectiveTemplate) {
|
|
320
|
+
this.autoCardTemplate = this.generateCardTemplate(this.entity);
|
|
321
|
+
}
|
|
322
|
+
if (this.standaloneMode && this.entity) {
|
|
323
|
+
this.loadData();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
ngOnChanges(changes) {
|
|
327
|
+
if (changes['entity'] && this.entity?.Fields) {
|
|
328
|
+
this.autoCardTemplate = this.generateCardTemplate(this.entity);
|
|
329
|
+
}
|
|
330
|
+
else if (changes['entity'] && !this.entity) {
|
|
331
|
+
this.autoCardTemplate = null;
|
|
332
|
+
}
|
|
333
|
+
if (changes['entity'] && this.standaloneMode && this.entity) {
|
|
334
|
+
this.loadData();
|
|
335
|
+
}
|
|
336
|
+
if (changes['records']) {
|
|
337
|
+
this.standaloneMode = this.records === null;
|
|
338
|
+
// When records change and we have a selection, scroll to it
|
|
339
|
+
if (this.selectedRecordId) {
|
|
340
|
+
this.pendingScrollToSelected = true;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// When selectedRecordId changes programmatically, scroll to the selected card
|
|
344
|
+
if (changes['selectedRecordId'] && this.selectedRecordId) {
|
|
345
|
+
this.pendingScrollToSelected = true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
ngAfterViewChecked() {
|
|
349
|
+
if (this.pendingScrollToSelected && this.selectedRecordId) {
|
|
350
|
+
this.pendingScrollToSelected = false;
|
|
351
|
+
// Delay scroll to allow detail panel animation to complete and layout to stabilize
|
|
352
|
+
// This ensures the scroll happens after the viewport width has adjusted
|
|
353
|
+
setTimeout(() => this.scrollToSelectedCard(), 350);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Scroll the selected card into view
|
|
358
|
+
*/
|
|
359
|
+
scrollToSelectedCard() {
|
|
360
|
+
if (!this.selectedRecordId)
|
|
361
|
+
return;
|
|
362
|
+
// Find the selected card element using the CSS class
|
|
363
|
+
const selectedCard = this.elementRef.nativeElement.querySelector('.data-card.selected');
|
|
364
|
+
if (selectedCard) {
|
|
365
|
+
selectedCard.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Get effective records (external or internal)
|
|
370
|
+
*/
|
|
371
|
+
get effectiveRecords() {
|
|
372
|
+
return this.records ?? this.internalRecords;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Load data in standalone mode
|
|
376
|
+
*/
|
|
377
|
+
async loadData() {
|
|
378
|
+
if (!this.entity)
|
|
379
|
+
return;
|
|
380
|
+
this.isLoading = true;
|
|
381
|
+
try {
|
|
382
|
+
const rv = new RunView();
|
|
383
|
+
const result = await rv.RunView({
|
|
384
|
+
EntityName: this.entity.Name,
|
|
385
|
+
ResultType: 'entity_object',
|
|
386
|
+
MaxRows: this.pageSize
|
|
387
|
+
});
|
|
388
|
+
if (result.Success) {
|
|
389
|
+
this.internalRecords = result.Results;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
console.error('Error loading cards data:', error);
|
|
394
|
+
}
|
|
395
|
+
finally {
|
|
396
|
+
this.isLoading = false;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Get the effective card template (custom or auto-generated)
|
|
401
|
+
*/
|
|
402
|
+
get effectiveTemplate() {
|
|
403
|
+
return this.cardTemplate || this.autoCardTemplate;
|
|
404
|
+
}
|
|
405
|
+
// ========================================
|
|
406
|
+
// TEMPLATE GENERATION
|
|
407
|
+
// ========================================
|
|
408
|
+
/**
|
|
409
|
+
* Generate card template from entity metadata
|
|
410
|
+
*/
|
|
411
|
+
generateCardTemplate(entity) {
|
|
412
|
+
const fields = entity.Fields;
|
|
413
|
+
if (!fields || fields.length === 0)
|
|
414
|
+
return null;
|
|
415
|
+
return {
|
|
416
|
+
titleField: this.findTitleField(entity, fields),
|
|
417
|
+
subtitleField: this.findSubtitleField(fields),
|
|
418
|
+
descriptionField: this.findDescriptionField(fields),
|
|
419
|
+
displayFields: this.findDisplayFields(fields),
|
|
420
|
+
thumbnailFields: this.findThumbnailFields(fields),
|
|
421
|
+
badgeField: this.findBadgeField(fields)
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
findTitleField(entity, fields) {
|
|
425
|
+
if (entity.NameField)
|
|
426
|
+
return entity.NameField.Name;
|
|
427
|
+
const nameField = fields.find(f => f.Name.toLowerCase() === 'name' || f.Name.toLowerCase() === 'title');
|
|
428
|
+
if (nameField)
|
|
429
|
+
return nameField.Name;
|
|
430
|
+
const endsWithName = fields.find(f => f.Name.toLowerCase().endsWith('name') &&
|
|
431
|
+
f.TSType === 'string' &&
|
|
432
|
+
!f.Name.toLowerCase().includes('file') &&
|
|
433
|
+
!f.IsPrimaryKey);
|
|
434
|
+
if (endsWithName)
|
|
435
|
+
return endsWithName.Name;
|
|
436
|
+
const firstString = fields.find(f => f.TSType === 'string' && !f.IsPrimaryKey && !f.Name.toLowerCase().includes('id'));
|
|
437
|
+
if (firstString)
|
|
438
|
+
return firstString.Name;
|
|
439
|
+
const pk = fields.find(f => f.IsPrimaryKey);
|
|
440
|
+
return pk?.Name || 'ID';
|
|
441
|
+
}
|
|
442
|
+
findSubtitleField(fields) {
|
|
443
|
+
const keywords = ['status', 'type', 'category', 'state', 'stage'];
|
|
444
|
+
for (const keyword of keywords) {
|
|
445
|
+
const field = fields.find(f => f.Name.toLowerCase().includes(keyword) && f.TSType === 'string' && !f.IsPrimaryKey);
|
|
446
|
+
if (field)
|
|
447
|
+
return field.Name;
|
|
448
|
+
}
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
findDescriptionField(fields) {
|
|
452
|
+
const keywords = ['description', 'desc', 'summary', 'notes', 'comments'];
|
|
453
|
+
for (const keyword of keywords) {
|
|
454
|
+
const field = fields.find(f => f.Name.toLowerCase().includes(keyword) && f.TSType === 'string');
|
|
455
|
+
if (field)
|
|
456
|
+
return field.Name;
|
|
457
|
+
}
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
findDisplayFields(fields) {
|
|
461
|
+
const displayFields = [];
|
|
462
|
+
const excludePatterns = ['id', 'name', 'title', 'description', 'desc', 'summary', 'notes',
|
|
463
|
+
'status', 'type', 'category', 'state', 'stage', 'password', 'secret',
|
|
464
|
+
'__mj_', 'createdat', 'updatedat', 'createdby', 'updatedby'];
|
|
465
|
+
const defaultInViewFields = fields.filter(f => f.DefaultInView === true && !f.IsPrimaryKey &&
|
|
466
|
+
!excludePatterns.some(p => f.Name.toLowerCase().includes(p)));
|
|
467
|
+
for (const field of defaultInViewFields) {
|
|
468
|
+
if (displayFields.length >= 4)
|
|
469
|
+
break;
|
|
470
|
+
displayFields.push({
|
|
471
|
+
name: field.Name,
|
|
472
|
+
type: this.getFieldType(field),
|
|
473
|
+
label: this.getFieldLabel(field)
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
if (displayFields.length >= 2)
|
|
477
|
+
return displayFields;
|
|
478
|
+
const metricKeywords = ['amount', 'total', 'count', 'value', 'price', 'cost', 'quantity', 'qty', 'balance', 'revenue', 'score'];
|
|
479
|
+
for (const field of fields) {
|
|
480
|
+
if (displayFields.length >= 4)
|
|
481
|
+
break;
|
|
482
|
+
if (displayFields.some(df => df.name === field.Name))
|
|
483
|
+
continue;
|
|
484
|
+
if (metricKeywords.some(kw => field.Name.toLowerCase().includes(kw))) {
|
|
485
|
+
displayFields.push({
|
|
486
|
+
name: field.Name,
|
|
487
|
+
type: this.getFieldType(field),
|
|
488
|
+
label: this.getFieldLabel(field)
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return displayFields;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Find all potential thumbnail fields in priority order
|
|
496
|
+
* Returns an array so we can fall back per-record if one is empty
|
|
497
|
+
*/
|
|
498
|
+
findThumbnailFields(fields) {
|
|
499
|
+
const imageKeywords = ['image', 'photo', 'picture', 'thumbnail', 'avatar', 'logo', 'icon'];
|
|
500
|
+
const foundFields = [];
|
|
501
|
+
const foundFieldNames = new Set();
|
|
502
|
+
for (const keyword of imageKeywords) {
|
|
503
|
+
const matchingFields = fields.filter(f => f.Name.toLowerCase().includes(keyword) &&
|
|
504
|
+
f.TSType === 'string' &&
|
|
505
|
+
!foundFieldNames.has(f.Name));
|
|
506
|
+
for (const field of matchingFields) {
|
|
507
|
+
foundFields.push(field.Name);
|
|
508
|
+
foundFieldNames.add(field.Name);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return foundFields;
|
|
512
|
+
}
|
|
513
|
+
findBadgeField(fields) {
|
|
514
|
+
const keywords = ['priority', 'severity', 'importance', 'rating', 'rank', 'level'];
|
|
515
|
+
for (const keyword of keywords) {
|
|
516
|
+
const field = fields.find(f => f.Name.toLowerCase().includes(keyword));
|
|
517
|
+
if (field)
|
|
518
|
+
return field.Name;
|
|
519
|
+
}
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
getFieldType(field) {
|
|
523
|
+
if (field.TSType === 'boolean' || field.Type?.toLowerCase() === 'bit')
|
|
524
|
+
return 'boolean';
|
|
525
|
+
if (field.TSType === 'number')
|
|
526
|
+
return 'number';
|
|
527
|
+
if (field.TSType === 'Date' || field.Type?.toLowerCase().includes('date'))
|
|
528
|
+
return 'date';
|
|
529
|
+
return 'text';
|
|
530
|
+
}
|
|
531
|
+
// ========================================
|
|
532
|
+
// VALUE FORMATTING
|
|
533
|
+
// ========================================
|
|
534
|
+
getFieldValue(record, fieldName) {
|
|
535
|
+
if (!fieldName)
|
|
536
|
+
return '';
|
|
537
|
+
const value = record.Get(fieldName);
|
|
538
|
+
if (value === null || value === undefined)
|
|
539
|
+
return '';
|
|
540
|
+
return String(value);
|
|
541
|
+
}
|
|
542
|
+
getNumericValue(record, fieldName) {
|
|
543
|
+
const value = record.Get(fieldName);
|
|
544
|
+
if (value === null || value === undefined)
|
|
545
|
+
return '-';
|
|
546
|
+
const num = Number(value);
|
|
547
|
+
if (isNaN(num))
|
|
548
|
+
return String(value);
|
|
549
|
+
if (num >= 1000000)
|
|
550
|
+
return `${(num / 1000000).toFixed(1)}M`;
|
|
551
|
+
if (num >= 1000)
|
|
552
|
+
return `${(num / 1000).toFixed(1)}K`;
|
|
553
|
+
const fieldNameLower = fieldName.toLowerCase();
|
|
554
|
+
if (['amount', 'price', 'cost', 'value', 'revenue', 'total'].some(k => fieldNameLower.includes(k))) {
|
|
555
|
+
return `$${num.toLocaleString()}`;
|
|
556
|
+
}
|
|
557
|
+
return num.toLocaleString();
|
|
558
|
+
}
|
|
559
|
+
getBooleanValue(record, fieldName) {
|
|
560
|
+
const value = record.Get(fieldName);
|
|
561
|
+
if (value === null || value === undefined)
|
|
562
|
+
return false;
|
|
563
|
+
if (typeof value === 'boolean')
|
|
564
|
+
return value;
|
|
565
|
+
if (typeof value === 'number')
|
|
566
|
+
return value !== 0;
|
|
567
|
+
if (typeof value === 'string')
|
|
568
|
+
return value.toLowerCase() === 'true' || value === '1';
|
|
569
|
+
return Boolean(value);
|
|
570
|
+
}
|
|
571
|
+
getTextValue(record, fieldName, maxLength = 50) {
|
|
572
|
+
const value = this.getFieldValue(record, fieldName);
|
|
573
|
+
if (!value)
|
|
574
|
+
return '-';
|
|
575
|
+
if (value.length <= maxLength)
|
|
576
|
+
return value;
|
|
577
|
+
return value.substring(0, maxLength) + '...';
|
|
578
|
+
}
|
|
579
|
+
getDateValue(record, fieldName) {
|
|
580
|
+
const value = record.Get(fieldName);
|
|
581
|
+
if (value === null || value === undefined)
|
|
582
|
+
return '-';
|
|
583
|
+
try {
|
|
584
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
585
|
+
if (isNaN(date.getTime()))
|
|
586
|
+
return String(value);
|
|
587
|
+
return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
|
|
588
|
+
}
|
|
589
|
+
catch {
|
|
590
|
+
return String(value);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Get display label for a field using EntityFieldInfo's built-in DisplayNameOrName property
|
|
595
|
+
*/
|
|
596
|
+
getFieldLabel(field) {
|
|
597
|
+
return field.DisplayNameOrName;
|
|
598
|
+
}
|
|
599
|
+
// ========================================
|
|
600
|
+
// CARD DISPLAY HELPERS
|
|
601
|
+
// ========================================
|
|
602
|
+
getRecordTrackId(record, index) {
|
|
603
|
+
try {
|
|
604
|
+
const pk = record?.PrimaryKey?.ToString();
|
|
605
|
+
if (pk && pk.trim().length > 0)
|
|
606
|
+
return pk;
|
|
607
|
+
}
|
|
608
|
+
catch { /* ignore */ }
|
|
609
|
+
return `record_${index}`;
|
|
610
|
+
}
|
|
611
|
+
isSelected(record) {
|
|
612
|
+
return record.PrimaryKey.ToConcatenatedString() === this.selectedRecordId;
|
|
613
|
+
}
|
|
614
|
+
onCardClick(record) {
|
|
615
|
+
if (!this.entity)
|
|
616
|
+
return;
|
|
617
|
+
this.recordSelected.emit({
|
|
618
|
+
record,
|
|
619
|
+
entity: this.entity,
|
|
620
|
+
compositeKey: record.PrimaryKey
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
onOpenClick(event, record) {
|
|
624
|
+
event.stopPropagation();
|
|
625
|
+
if (!this.entity)
|
|
626
|
+
return;
|
|
627
|
+
this.recordOpened.emit({
|
|
628
|
+
record,
|
|
629
|
+
entity: this.entity,
|
|
630
|
+
compositeKey: record.PrimaryKey
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
getInitials(record) {
|
|
634
|
+
const template = this.effectiveTemplate;
|
|
635
|
+
if (!template?.titleField)
|
|
636
|
+
return '?';
|
|
637
|
+
const title = this.getFieldValue(record, template.titleField);
|
|
638
|
+
if (!title)
|
|
639
|
+
return '?';
|
|
640
|
+
const words = title.split(/\s+/).filter(w => w.length > 0);
|
|
641
|
+
if (words.length === 1)
|
|
642
|
+
return words[0].substring(0, 2).toUpperCase();
|
|
643
|
+
return (words[0][0] + words[1][0]).toUpperCase();
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Get the thumbnail type for a record, with per-record fallback through thumbnailFields
|
|
647
|
+
*/
|
|
648
|
+
getThumbnailType(record) {
|
|
649
|
+
const fieldInfo = this.getEffectiveThumbnailField(record);
|
|
650
|
+
if (!fieldInfo)
|
|
651
|
+
return 'none';
|
|
652
|
+
const { fieldName, value } = fieldInfo;
|
|
653
|
+
// Check if value is an image URL
|
|
654
|
+
if (this.isImageValue(value))
|
|
655
|
+
return 'image';
|
|
656
|
+
// Check if value looks like an icon class
|
|
657
|
+
if (this.isIconClass(value))
|
|
658
|
+
return 'icon';
|
|
659
|
+
// If field name suggests it's an icon field, treat non-URL values as icon classes
|
|
660
|
+
const fieldNameLower = fieldName.toLowerCase();
|
|
661
|
+
if (fieldNameLower.includes('icon') || fieldNameLower.includes('class')) {
|
|
662
|
+
return 'icon';
|
|
663
|
+
}
|
|
664
|
+
return 'none';
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Get the thumbnail URL/value for a record, with per-record fallback
|
|
668
|
+
*/
|
|
669
|
+
getThumbnailUrl(record) {
|
|
670
|
+
const fieldInfo = this.getEffectiveThumbnailField(record);
|
|
671
|
+
return fieldInfo?.value || '';
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Find the first thumbnail field that has a value for this record
|
|
675
|
+
* Returns both the field name and value for type determination
|
|
676
|
+
*/
|
|
677
|
+
getEffectiveThumbnailField(record) {
|
|
678
|
+
const template = this.effectiveTemplate;
|
|
679
|
+
if (!template?.thumbnailFields || template.thumbnailFields.length === 0)
|
|
680
|
+
return null;
|
|
681
|
+
// Try each field in priority order until we find one with a value
|
|
682
|
+
for (const fieldName of template.thumbnailFields) {
|
|
683
|
+
const value = this.getFieldValue(record, fieldName);
|
|
684
|
+
if (value && value.trim() !== '') {
|
|
685
|
+
return { fieldName, value };
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
isImageValue(value) {
|
|
691
|
+
if (!value)
|
|
692
|
+
return false;
|
|
693
|
+
const trimmed = value.trim();
|
|
694
|
+
if (trimmed.startsWith('data:image/'))
|
|
695
|
+
return true;
|
|
696
|
+
if (trimmed.startsWith('http://') || trimmed.startsWith('https://'))
|
|
697
|
+
return true;
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
isIconClass(value) {
|
|
701
|
+
if (!value)
|
|
702
|
+
return false;
|
|
703
|
+
const trimmed = value.trim().toLowerCase();
|
|
704
|
+
if (trimmed.startsWith('fa-') || trimmed.startsWith('fa ') ||
|
|
705
|
+
trimmed.startsWith('fas ') || trimmed.startsWith('far ') ||
|
|
706
|
+
trimmed.startsWith('fal ') || trimmed.startsWith('fab '))
|
|
707
|
+
return true;
|
|
708
|
+
if (trimmed.includes('material-icons') || trimmed.startsWith('mat-icon'))
|
|
709
|
+
return true;
|
|
710
|
+
if (trimmed.startsWith('bi-') || trimmed.startsWith('bi '))
|
|
711
|
+
return true;
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
getRecordColor(record) {
|
|
715
|
+
const colors = ['#1976d2', '#388e3c', '#f57c00', '#7b1fa2', '#c2185b', '#0097a7', '#5d4037', '#455a64'];
|
|
716
|
+
const pk = record.PrimaryKey.ToString();
|
|
717
|
+
let hash = 0;
|
|
718
|
+
for (let i = 0; i < pk.length; i++) {
|
|
719
|
+
hash = pk.charCodeAt(i) + ((hash << 5) - hash);
|
|
720
|
+
}
|
|
721
|
+
return colors[Math.abs(hash) % colors.length];
|
|
722
|
+
}
|
|
723
|
+
isEnumField(fieldName) {
|
|
724
|
+
if (!this.entity)
|
|
725
|
+
return false;
|
|
726
|
+
const field = this.entity.Fields.find(f => f.Name === fieldName);
|
|
727
|
+
if (!field)
|
|
728
|
+
return false;
|
|
729
|
+
return field.ValueListTypeEnum !== EntityFieldValueListType.None && field.EntityFieldValues.length > 0;
|
|
730
|
+
}
|
|
731
|
+
get subtitleIsPill() {
|
|
732
|
+
const template = this.effectiveTemplate;
|
|
733
|
+
if (!template?.subtitleField || !this.entity)
|
|
734
|
+
return false;
|
|
735
|
+
return this.isEnumField(template.subtitleField);
|
|
736
|
+
}
|
|
737
|
+
getPillColorType(value) {
|
|
738
|
+
return PillColorUtil.getColorType(value);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Check if a record matched on a hidden field
|
|
742
|
+
*/
|
|
743
|
+
hasHiddenFieldMatch(record) {
|
|
744
|
+
return this.hiddenFieldMatches.has(record.PrimaryKey.ToConcatenatedString());
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Get the display name of the hidden field that matched
|
|
748
|
+
*/
|
|
749
|
+
getHiddenMatchFieldName(record) {
|
|
750
|
+
const fieldName = this.hiddenFieldMatches.get(record.PrimaryKey.ToConcatenatedString());
|
|
751
|
+
if (!fieldName || !this.entity)
|
|
752
|
+
return '';
|
|
753
|
+
// Look up the field in entity metadata and use DisplayNameOrName
|
|
754
|
+
const field = this.entity.Fields.find(f => f.Name === fieldName);
|
|
755
|
+
return field ? field.DisplayNameOrName : fieldName;
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Highlight matching text in a string based on the filter text
|
|
759
|
+
* Uses HighlightUtil which only highlights if the text actually matches the pattern
|
|
760
|
+
*/
|
|
761
|
+
highlightMatch(text) {
|
|
762
|
+
return HighlightUtil.highlight(text, this.filterText, false);
|
|
763
|
+
}
|
|
764
|
+
static ɵfac = function EntityCardsComponent_Factory(t) { return new (t || EntityCardsComponent)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
765
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityCardsComponent, selectors: [["mj-entity-cards"]], inputs: { entity: "entity", records: "records", selectedRecordId: "selectedRecordId", cardTemplate: "cardTemplate", hiddenFieldMatches: "hiddenFieldMatches", filterText: "filterText", pageSize: "pageSize" }, outputs: { recordSelected: "recordSelected", recordOpened: "recordOpened" }, features: [i0.ɵɵNgOnChangesFeature], decls: 3, vars: 1, consts: [[1, "cards-view-wrapper"], [1, "loading-container"], [1, "cards-container"], ["text", "Loading records..."], [1, "data-card", 3, "selected"], [1, "no-results"], [1, "data-card", 3, "click"], [1, "card-header"], [1, "card-thumbnail"], [1, "card-avatar", 3, "background-color"], [1, "card-header-content"], [1, "card-title", 3, "innerHTML"], ["title", "Open Record", 1, "card-open-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "card-body"], [1, "card-description", 3, "innerHTML"], [1, "card-fields"], [1, "card-footer"], [1, "hidden-match-indicator", 3, "title"], ["alt", "", 3, "src"], [1, "card-avatar"], [3, "value"], [1, "card-subtitle", 3, "innerHTML"], [1, "field-item", 3, "field-boolean", "field-text"], [1, "field-item"], [1, "field-icon"], [1, "field-label"], [1, "field-value"], [1, "field-value", "field-date"], [1, "field-text-value", 3, "innerHTML"], [1, "fa-solid", "fa-magnifying-glass"], [1, "fa-solid", "fa-inbox"]], template: function EntityCardsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
766
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
767
|
+
i0.ɵɵtemplate(1, EntityCardsComponent_Conditional_1_Template, 2, 0, "div", 1)(2, EntityCardsComponent_Conditional_2_Template, 4, 1, "div", 2);
|
|
768
|
+
i0.ɵɵelementEnd();
|
|
769
|
+
} if (rf & 2) {
|
|
770
|
+
i0.ɵɵadvance();
|
|
771
|
+
i0.ɵɵconditional(ctx.isLoading && ctx.effectiveRecords.length === 0 ? 1 : 2);
|
|
772
|
+
} }, dependencies: [i1.LoadingComponent, i2.PillComponent], styles: [".cards-view-wrapper[_ngcontent-%COMP%] {\n height: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.cards-container[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 20px;\n padding: 4px;\n}\n\n.data-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n\n.data-card[_ngcontent-%COMP%]:hover:not(.selected) {\n border-color: #bdbdbd;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n transform: translateY(-2px);\n}\n.data-card[_ngcontent-%COMP%]:hover .card-open-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n.data-card.selected[_ngcontent-%COMP%] {\n border-color: #1976d2;\n}\n\n.data-card.selected[_ngcontent-%COMP%] .card-title[_ngcontent-%COMP%] {\n color: #1565c0;\n}\n\n\n\n.data-card.selected[_ngcontent-%COMP%]:hover {\n border-color: #1976d2;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n transform: translateY(-2px);\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n padding: 16px;\n gap: 12px;\n}\n\n.card-thumbnail[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 8px;\n overflow: hidden;\n flex-shrink: 0;\n}\n.card-thumbnail[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.card-avatar[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n font-weight: 600;\n color: white;\n flex-shrink: 0;\n}\n\n.card-header-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.card-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: #212121;\n line-height: 1.3;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.card-subtitle[_ngcontent-%COMP%] {\n display: block;\n margin-top: 2px;\n font-size: 12px;\n color: #757575;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-open-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: #9e9e9e;\n opacity: 0;\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.card-open-btn[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n color: #1976d2;\n}\n\n.card-body[_ngcontent-%COMP%] {\n padding: 0 16px 16px 16px;\n}\n\n.card-description[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 13px;\n color: #616161;\n line-height: 1.5;\n}\n\n\n\n.card-fields[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid #f0f0f0;\n}\n\n.field-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 60px;\n}\n\n.field-item[_ngcontent-%COMP%] .field-value[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: #212121;\n}\n\n.field-item[_ngcontent-%COMP%] .field-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #9e9e9e;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n\n\n.field-item.field-boolean[_ngcontent-%COMP%] {\n flex-direction: row;\n align-items: center;\n gap: 6px;\n min-width: auto;\n}\n\n.field-item.field-boolean[_ngcontent-%COMP%] .field-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.field-item.field-boolean[_ngcontent-%COMP%] .field-icon.bool-true[_ngcontent-%COMP%] {\n color: #2e7d32;\n}\n\n.field-item.field-boolean[_ngcontent-%COMP%] .field-icon.bool-false[_ngcontent-%COMP%] {\n color: #bdbdbd;\n}\n\n.field-item.field-boolean[_ngcontent-%COMP%] .field-label[_ngcontent-%COMP%] {\n font-size: 12px;\n text-transform: none;\n color: #616161;\n}\n\n\n\n.field-item.field-text[_ngcontent-%COMP%] {\n flex: 1 1 100%;\n max-width: 100%;\n}\n\n.field-item[_ngcontent-%COMP%] .field-text-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #424242;\n line-height: 1.4;\n word-break: break-word;\n}\n\n\n\n.field-item[_ngcontent-%COMP%] .field-date[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n}\n\n.card-footer[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: #fafafa;\n border-top: 1px solid #f0f0f0;\n}\n\n\n\n .highlight-match {\n background-color: #fff176;\n border-radius: 2px;\n}\n\n\n\n.card-header-content[_ngcontent-%COMP%] mj-pill[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n}\n\n\n\n.hidden-match-indicator[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: #fff8e1;\n border-top: 1px solid #ffe082;\n font-size: 11px;\n color: #f57c00;\n}\n\n.hidden-match-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.hidden-match-indicator[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n padding: 40px;\n}\n\n\n\n.no-results[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: #9e9e9e;\n text-align: center;\n}\n.no-results[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n.no-results[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}"] });
|
|
773
|
+
}
|
|
774
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityCardsComponent, [{
|
|
775
|
+
type: Component,
|
|
776
|
+
args: [{ selector: 'mj-entity-cards', template: "<div class=\"cards-view-wrapper\">\n @if (isLoading && effectiveRecords.length === 0) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading records...\"></mj-loading>\n </div>\n } @else {\n <div class=\"cards-container\">\n @for (record of effectiveRecords; track getRecordTrackId(record, $index)) {\n <div\n class=\"data-card\"\n [class.selected]=\"isSelected(record)\"\n (click)=\"onCardClick(record)\">\n\n <!-- Card Header with Avatar/Icon -->\n <div class=\"card-header\">\n @switch (getThumbnailType(record)) {\n @case ('image') {\n <div class=\"card-thumbnail\">\n <img [src]=\"getThumbnailUrl(record)\" alt=\"\" />\n </div>\n }\n @case ('icon') {\n <div class=\"card-avatar\" [style.background-color]=\"getRecordColor(record)\">\n <i [class]=\"getThumbnailUrl(record)\"></i>\n </div>\n }\n @default {\n <div class=\"card-avatar\" [style.background-color]=\"getRecordColor(record)\">\n {{ getInitials(record) }}\n </div>\n }\n }\n\n <div class=\"card-header-content\">\n <h3 class=\"card-title\" [innerHTML]=\"highlightMatch(getFieldValue(record, effectiveTemplate?.titleField ?? null))\"></h3>\n @if (effectiveTemplate?.subtitleField; as subField) {\n @if (subtitleIsPill) {\n <mj-pill [value]=\"getFieldValue(record, subField)\"></mj-pill>\n } @else {\n <span class=\"card-subtitle\" [innerHTML]=\"highlightMatch(getFieldValue(record, subField))\"></span>\n }\n }\n </div>\n\n <button class=\"card-open-btn\" (click)=\"onOpenClick($event, record)\" title=\"Open Record\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n </div>\n\n <!-- Card Body -->\n <div class=\"card-body\">\n @if (effectiveTemplate?.descriptionField; as descField) {\n <p class=\"card-description\" [innerHTML]=\"highlightMatch(getTextValue(record, descField, 100))\"></p>\n }\n\n <!-- Display Fields -->\n @if (effectiveTemplate && effectiveTemplate.displayFields.length > 0) {\n <div class=\"card-fields\">\n @for (field of effectiveTemplate.displayFields; track field.name) {\n <div class=\"field-item\" [class.field-boolean]=\"field.type === 'boolean'\" [class.field-text]=\"field.type === 'text'\">\n @switch (field.type) {\n @case ('boolean') {\n <i class=\"field-icon\" [class.fa-solid]=\"true\"\n [class.fa-check]=\"getBooleanValue(record, field.name)\"\n [class.fa-minus]=\"!getBooleanValue(record, field.name)\"\n [class.bool-true]=\"getBooleanValue(record, field.name)\"\n [class.bool-false]=\"!getBooleanValue(record, field.name)\"></i>\n <span class=\"field-label\">{{ field.label }}</span>\n }\n @case ('number') {\n <span class=\"field-value\">{{ getNumericValue(record, field.name) }}</span>\n <span class=\"field-label\">{{ field.label }}</span>\n }\n @case ('date') {\n <span class=\"field-value field-date\">{{ getDateValue(record, field.name) }}</span>\n <span class=\"field-label\">{{ field.label }}</span>\n }\n @default {\n <span class=\"field-label\">{{ field.label }}</span>\n <span class=\"field-text-value\" [innerHTML]=\"highlightMatch(getTextValue(record, field.name, 40))\"></span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Card Footer with Badge -->\n @if (effectiveTemplate?.badgeField; as badgeField) {\n <div class=\"card-footer\">\n <mj-pill [value]=\"getFieldValue(record, badgeField)\"></mj-pill>\n </div>\n }\n\n <!-- Hidden field match indicator -->\n @if (hasHiddenFieldMatch(record)) {\n <div class=\"hidden-match-indicator\" [title]=\"'Matched in: ' + getHiddenMatchFieldName(record)\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <span>{{ getHiddenMatchFieldName(record) }}</span>\n </div>\n }\n </div>\n }\n\n @if (effectiveRecords.length === 0) {\n <div class=\"no-results\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No records to display</p>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".cards-view-wrapper {\n height: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.cards-container {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 20px;\n padding: 4px;\n}\n\n.data-card {\n background: white;\n border-radius: 12px;\n border: 1px solid #e0e0e0;\n overflow: hidden;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n/* Hover state for unselected cards */\n.data-card:hover:not(.selected) {\n border-color: #bdbdbd;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n transform: translateY(-2px);\n}\n.data-card:hover .card-open-btn {\n opacity: 1;\n}\n\n/* Selected state - subtle but clear */\n.data-card.selected {\n border-color: #1976d2;\n}\n\n.data-card.selected .card-title {\n color: #1565c0;\n}\n\n/* Selected + hover state - same as regular hover */\n.data-card.selected:hover {\n border-color: #1976d2;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n transform: translateY(-2px);\n}\n\n.card-header {\n display: flex;\n align-items: flex-start;\n padding: 16px;\n gap: 12px;\n}\n\n.card-thumbnail {\n width: 48px;\n height: 48px;\n border-radius: 8px;\n overflow: hidden;\n flex-shrink: 0;\n}\n.card-thumbnail img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.card-avatar {\n width: 48px;\n height: 48px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n font-weight: 600;\n color: white;\n flex-shrink: 0;\n}\n\n.card-header-content {\n flex: 1;\n min-width: 0;\n}\n\n.card-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: #212121;\n line-height: 1.3;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.card-subtitle {\n display: block;\n margin-top: 2px;\n font-size: 12px;\n color: #757575;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-open-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: #9e9e9e;\n opacity: 0;\n transition: all 0.15s ease;\n flex-shrink: 0;\n}\n.card-open-btn:hover {\n background: #f5f5f5;\n color: #1976d2;\n}\n\n.card-body {\n padding: 0 16px 16px 16px;\n}\n\n.card-description {\n margin: 0 0 12px 0;\n font-size: 13px;\n color: #616161;\n line-height: 1.5;\n}\n\n/* Card Display Fields */\n.card-fields {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid #f0f0f0;\n}\n\n.field-item {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 60px;\n}\n\n.field-item .field-value {\n font-size: 15px;\n font-weight: 600;\n color: #212121;\n}\n\n.field-item .field-label {\n font-size: 10px;\n color: #9e9e9e;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* Boolean fields */\n.field-item.field-boolean {\n flex-direction: row;\n align-items: center;\n gap: 6px;\n min-width: auto;\n}\n\n.field-item.field-boolean .field-icon {\n font-size: 14px;\n}\n\n.field-item.field-boolean .field-icon.bool-true {\n color: #2e7d32;\n}\n\n.field-item.field-boolean .field-icon.bool-false {\n color: #bdbdbd;\n}\n\n.field-item.field-boolean .field-label {\n font-size: 12px;\n text-transform: none;\n color: #616161;\n}\n\n/* Text fields */\n.field-item.field-text {\n flex: 1 1 100%;\n max-width: 100%;\n}\n\n.field-item .field-text-value {\n font-size: 13px;\n color: #424242;\n line-height: 1.4;\n word-break: break-word;\n}\n\n/* Date fields */\n.field-item .field-date {\n font-size: 13px;\n font-weight: 500;\n}\n\n.card-footer {\n padding: 12px 16px;\n background: #fafafa;\n border-top: 1px solid #f0f0f0;\n}\n\n/* Highlight matches */\n::ng-deep .highlight-match {\n background-color: #fff176;\n border-radius: 2px;\n}\n\n/* Pill spacing when used as subtitle */\n.card-header-content mj-pill {\n display: block;\n margin-top: 4px;\n}\n\n/* Hidden field match indicator */\n.hidden-match-indicator {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: #fff8e1;\n border-top: 1px solid #ffe082;\n font-size: 11px;\n color: #f57c00;\n}\n\n.hidden-match-indicator i {\n font-size: 10px;\n}\n\n.hidden-match-indicator span {\n font-weight: 500;\n}\n\n/* Loading state */\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n padding: 40px;\n}\n\n/* No results state */\n.no-results {\n grid-column: 1 / -1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: #9e9e9e;\n text-align: center;\n}\n.no-results i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n.no-results p {\n margin: 0;\n font-size: 14px;\n}\n"] }]
|
|
777
|
+
}], () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], { entity: [{
|
|
778
|
+
type: Input
|
|
779
|
+
}], records: [{
|
|
780
|
+
type: Input
|
|
781
|
+
}], selectedRecordId: [{
|
|
782
|
+
type: Input
|
|
783
|
+
}], cardTemplate: [{
|
|
784
|
+
type: Input
|
|
785
|
+
}], hiddenFieldMatches: [{
|
|
786
|
+
type: Input
|
|
787
|
+
}], filterText: [{
|
|
788
|
+
type: Input
|
|
789
|
+
}], pageSize: [{
|
|
790
|
+
type: Input
|
|
791
|
+
}], recordSelected: [{
|
|
792
|
+
type: Output
|
|
793
|
+
}], recordOpened: [{
|
|
794
|
+
type: Output
|
|
795
|
+
}] }); })();
|
|
796
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityCardsComponent, { className: "EntityCardsComponent" }); })();
|
|
797
|
+
//# sourceMappingURL=entity-cards.component.js.map
|