@memberjunction/ng-dashboards 2.122.2 → 2.123.1
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/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +79 -0
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +1 -0
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +195 -0
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +1 -0
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts +67 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js +377 -79
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +87 -4
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +517 -209
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +13 -2
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.js +3 -0
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts +2 -2
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/module.d.ts +28 -26
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +10 -3
- package/dist/module.js.map +1 -1
- package/package.json +25 -24
|
@@ -11,25 +11,30 @@ import { Subject } from 'rxjs';
|
|
|
11
11
|
import { takeUntil, debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';
|
|
12
12
|
import { BaseDashboard } from '@memberjunction/ng-shared';
|
|
13
13
|
import { RegisterClass } from '@memberjunction/global';
|
|
14
|
-
import { Metadata, RunView,
|
|
14
|
+
import { Metadata, RunView, EntityFieldTSType } from '@memberjunction/core';
|
|
15
15
|
import { EntityViewerComponent } from '@memberjunction/ng-entity-viewer';
|
|
16
16
|
import { ViewSelectorComponent } from './components/view-selector/view-selector.component';
|
|
17
|
+
import { ViewConfigPanelComponent } from './components/view-config-panel/view-config-panel.component';
|
|
18
|
+
import { createEmptyFilter } from '@memberjunction/ng-filter-builder';
|
|
17
19
|
import * as i0 from "@angular/core";
|
|
18
20
|
import * as i1 from "./services/explorer-state.service";
|
|
19
21
|
import * as i2 from "@angular/router";
|
|
20
22
|
import * as i3 from "@memberjunction/ng-shared-generic";
|
|
21
|
-
import * as i4 from "@
|
|
22
|
-
import * as i5 from "@
|
|
23
|
-
import * as i6 from "
|
|
24
|
-
import * as i7 from "./components/
|
|
25
|
-
import * as i8 from "./components/view-
|
|
26
|
-
import * as i9 from "
|
|
23
|
+
import * as i4 from "@memberjunction/ng-shared";
|
|
24
|
+
import * as i5 from "@angular/forms";
|
|
25
|
+
import * as i6 from "@memberjunction/ng-entity-viewer";
|
|
26
|
+
import * as i7 from "./components/navigation-panel/navigation-panel.component";
|
|
27
|
+
import * as i8 from "./components/view-selector/view-selector.component";
|
|
28
|
+
import * as i9 from "./components/view-config-panel/view-config-panel.component";
|
|
29
|
+
import * as i10 from "./components/filter-dialog/filter-dialog.component";
|
|
30
|
+
import * as i11 from "@angular/common";
|
|
27
31
|
const _c0 = ["filterInput"];
|
|
28
32
|
const _forTrack0 = ($index, $item) => $item.label;
|
|
29
|
-
const _forTrack1 = ($index, $item) => $item.
|
|
30
|
-
const _forTrack2 = ($index, $item) => $item.
|
|
31
|
-
const _forTrack3 = ($index, $item) => $item.entityId;
|
|
32
|
-
const _forTrack4 = ($index, $item) => $item.
|
|
33
|
+
const _forTrack1 = ($index, $item) => $item.name;
|
|
34
|
+
const _forTrack2 = ($index, $item) => $item.ID;
|
|
35
|
+
const _forTrack3 = ($index, $item) => $item.entityId + "|" + $item.recordId;
|
|
36
|
+
const _forTrack4 = ($index, $item) => $item.entityId;
|
|
37
|
+
const _forTrack5 = ($index, $item) => $item.userFavoriteId;
|
|
33
38
|
function DataExplorerDashboardComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
34
39
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
35
40
|
i0.ɵɵelementStart(0, "div", 16)(1, "mj-explorer-navigation-panel", 17);
|
|
@@ -192,238 +197,358 @@ function DataExplorerDashboardComponent_Conditional_10_Template(rf, ctx) { if (r
|
|
|
192
197
|
i0.ɵɵadvance(2);
|
|
193
198
|
i0.ɵɵconditional(ctx_r1.entityFilterText ? 4 : -1);
|
|
194
199
|
} }
|
|
200
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
201
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
202
|
+
i0.ɵɵelementStart(0, "button", 40);
|
|
203
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onViewModeChanged("timeline")); });
|
|
204
|
+
i0.ɵɵelement(1, "i", 41);
|
|
205
|
+
i0.ɵɵelementEnd();
|
|
206
|
+
} if (rf & 2) {
|
|
207
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
208
|
+
i0.ɵɵclassProp("active", ctx_r1.state.viewMode === "timeline");
|
|
209
|
+
} }
|
|
210
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
211
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
212
|
+
i0.ɵɵelementStart(0, "div", 53);
|
|
213
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_1_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.closeDateFieldDropdown()); });
|
|
214
|
+
i0.ɵɵelementEnd();
|
|
215
|
+
} }
|
|
216
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
217
|
+
i0.ɵɵelement(0, "i", 54);
|
|
218
|
+
} if (rf & 2) {
|
|
219
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
220
|
+
i0.ɵɵclassProp("rotated", ctx_r1.isDateFieldDropdownOpen);
|
|
221
|
+
} }
|
|
222
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
223
|
+
i0.ɵɵelement(0, "i", 59);
|
|
224
|
+
} }
|
|
225
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
226
|
+
const _r17 = i0.ɵɵgetCurrentView();
|
|
227
|
+
i0.ɵɵelementStart(0, "div", 56);
|
|
228
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_For_2_Template_div_click_0_listener() { const field_r18 = i0.ɵɵrestoreView(_r17).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.setTimelineDateField(field_r18.name)); });
|
|
229
|
+
i0.ɵɵelement(1, "i", 57);
|
|
230
|
+
i0.ɵɵelementStart(2, "span", 58);
|
|
231
|
+
i0.ɵɵtext(3);
|
|
232
|
+
i0.ɵɵelementEnd();
|
|
233
|
+
i0.ɵɵtemplate(4, DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_For_2_Conditional_4_Template, 1, 0, "i", 59);
|
|
234
|
+
i0.ɵɵelementEnd();
|
|
235
|
+
} if (rf & 2) {
|
|
236
|
+
const field_r18 = ctx.$implicit;
|
|
237
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
238
|
+
i0.ɵɵclassProp("selected", field_r18.name === ctx_r1.effectiveTimelineDateField);
|
|
239
|
+
i0.ɵɵadvance(3);
|
|
240
|
+
i0.ɵɵtextInterpolate(field_r18.displayName);
|
|
241
|
+
i0.ɵɵadvance();
|
|
242
|
+
i0.ɵɵconditional(field_r18.name === ctx_r1.effectiveTimelineDateField ? 4 : -1);
|
|
243
|
+
} }
|
|
244
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
245
|
+
i0.ɵɵelementStart(0, "div", 49);
|
|
246
|
+
i0.ɵɵrepeaterCreate(1, DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_For_2_Template, 5, 4, "div", 55, _forTrack1);
|
|
247
|
+
i0.ɵɵelementEnd();
|
|
248
|
+
} if (rf & 2) {
|
|
249
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
250
|
+
i0.ɵɵadvance();
|
|
251
|
+
i0.ɵɵrepeater(ctx_r1.availableDateFields);
|
|
252
|
+
} }
|
|
253
|
+
function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
254
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
255
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
256
|
+
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_1_Template, 1, 0, "div", 43);
|
|
257
|
+
i0.ɵɵelementStart(2, "div", 44)(3, "button", 45);
|
|
258
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleDateFieldDropdown()); });
|
|
259
|
+
i0.ɵɵelement(4, "i", 46);
|
|
260
|
+
i0.ɵɵelementStart(5, "span", 47);
|
|
261
|
+
i0.ɵɵtext(6);
|
|
262
|
+
i0.ɵɵelementEnd();
|
|
263
|
+
i0.ɵɵtemplate(7, DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_7_Template, 1, 2, "i", 48);
|
|
264
|
+
i0.ɵɵelementEnd();
|
|
265
|
+
i0.ɵɵtemplate(8, DataExplorerDashboardComponent_Conditional_12_Conditional_6_Conditional_8_Template, 3, 0, "div", 49);
|
|
266
|
+
i0.ɵɵelementEnd()();
|
|
267
|
+
i0.ɵɵelementStart(9, "div", 50)(10, "button", 51);
|
|
268
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleTimelineOrientation()); });
|
|
269
|
+
i0.ɵɵelement(11, "i");
|
|
270
|
+
i0.ɵɵelementEnd()();
|
|
271
|
+
i0.ɵɵelementStart(12, "div", 52)(13, "button", 51);
|
|
272
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Conditional_6_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleTimelineSortOrder()); });
|
|
273
|
+
i0.ɵɵelement(14, "i");
|
|
274
|
+
i0.ɵɵelementEnd()();
|
|
275
|
+
} if (rf & 2) {
|
|
276
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
277
|
+
i0.ɵɵadvance();
|
|
278
|
+
i0.ɵɵconditional(ctx_r1.isDateFieldDropdownOpen ? 1 : -1);
|
|
279
|
+
i0.ɵɵadvance(2);
|
|
280
|
+
i0.ɵɵclassProp("open", ctx_r1.isDateFieldDropdownOpen);
|
|
281
|
+
i0.ɵɵproperty("disabled", ctx_r1.availableDateFields.length <= 1);
|
|
282
|
+
i0.ɵɵadvance(3);
|
|
283
|
+
i0.ɵɵtextInterpolate(ctx_r1.effectiveTimelineDateFieldDisplayName);
|
|
284
|
+
i0.ɵɵadvance();
|
|
285
|
+
i0.ɵɵconditional(ctx_r1.availableDateFields.length > 1 ? 7 : -1);
|
|
286
|
+
i0.ɵɵadvance();
|
|
287
|
+
i0.ɵɵconditional(ctx_r1.isDateFieldDropdownOpen && ctx_r1.availableDateFields.length > 1 ? 8 : -1);
|
|
288
|
+
i0.ɵɵadvance(2);
|
|
289
|
+
i0.ɵɵproperty("title", ctx_r1.state.timelineOrientation === "vertical" ? "Switch to Horizontal" : "Switch to Vertical");
|
|
290
|
+
i0.ɵɵadvance();
|
|
291
|
+
i0.ɵɵclassMap(ctx_r1.state.timelineOrientation === "vertical" ? "fa-solid fa-ellipsis-vertical" : "fa-solid fa-ellipsis");
|
|
292
|
+
i0.ɵɵadvance(2);
|
|
293
|
+
i0.ɵɵproperty("title", ctx_r1.state.timelineSortOrder === "desc" ? "Showing Newest First (click for Oldest First)" : "Showing Oldest First (click for Newest First)");
|
|
294
|
+
i0.ɵɵadvance();
|
|
295
|
+
i0.ɵɵclassMap(ctx_r1.state.timelineSortOrder === "desc" ? "fa-solid fa-arrow-down-wide-short" : "fa-solid fa-arrow-up-wide-short");
|
|
296
|
+
} }
|
|
195
297
|
function DataExplorerDashboardComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
196
298
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
197
|
-
i0.ɵɵelementStart(0, "div",
|
|
299
|
+
i0.ɵɵelementStart(0, "div", 34)(1, "button", 35);
|
|
198
300
|
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onViewModeChanged("grid")); });
|
|
199
|
-
i0.ɵɵelement(2, "i",
|
|
301
|
+
i0.ɵɵelement(2, "i", 36);
|
|
200
302
|
i0.ɵɵelementEnd();
|
|
201
|
-
i0.ɵɵelementStart(3, "button",
|
|
303
|
+
i0.ɵɵelementStart(3, "button", 37);
|
|
202
304
|
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_12_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onViewModeChanged("cards")); });
|
|
203
|
-
i0.ɵɵelement(4, "i",
|
|
204
|
-
i0.ɵɵelementEnd()
|
|
305
|
+
i0.ɵɵelement(4, "i", 38);
|
|
306
|
+
i0.ɵɵelementEnd();
|
|
307
|
+
i0.ɵɵtemplate(5, DataExplorerDashboardComponent_Conditional_12_Conditional_5_Template, 2, 2, "button", 39);
|
|
308
|
+
i0.ɵɵelementEnd();
|
|
309
|
+
i0.ɵɵtemplate(6, DataExplorerDashboardComponent_Conditional_12_Conditional_6_Template, 15, 13);
|
|
205
310
|
} if (rf & 2) {
|
|
206
311
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
207
312
|
i0.ɵɵadvance();
|
|
208
313
|
i0.ɵɵclassProp("active", ctx_r1.state.viewMode === "grid");
|
|
209
314
|
i0.ɵɵadvance(2);
|
|
210
315
|
i0.ɵɵclassProp("active", ctx_r1.state.viewMode === "cards");
|
|
316
|
+
i0.ɵɵadvance(2);
|
|
317
|
+
i0.ɵɵconditional(ctx_r1.entityHasDateFields ? 5 : -1);
|
|
318
|
+
i0.ɵɵadvance();
|
|
319
|
+
i0.ɵɵconditional(ctx_r1.state.viewMode === "timeline" && ctx_r1.entityHasDateFields ? 6 : -1);
|
|
211
320
|
} }
|
|
212
321
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
213
|
-
i0.ɵɵelementStart(0, "div",
|
|
214
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
322
|
+
i0.ɵɵelementStart(0, "div", 60);
|
|
323
|
+
i0.ɵɵelement(1, "mj-loading", 62);
|
|
215
324
|
i0.ɵɵelementEnd();
|
|
216
325
|
} }
|
|
217
|
-
function
|
|
218
|
-
const
|
|
219
|
-
i0.ɵɵelementStart(0, "button",
|
|
220
|
-
i0.ɵɵlistener("click", function
|
|
326
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Conditional_5_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
327
|
+
const _r20 = i0.ɵɵgetCurrentView();
|
|
328
|
+
i0.ɵɵelementStart(0, "button", 84);
|
|
329
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Conditional_5_For_4_Template_button_click_0_listener() { const entity_r21 = i0.ɵɵrestoreView(_r20).$implicit; const ctx_r1 = i0.ɵɵnextContext(7); return i0.ɵɵresetView(ctx_r1.setRecentRecordsEntityFilter(entity_r21.entityId)); });
|
|
221
330
|
i0.ɵɵelement(1, "i");
|
|
222
331
|
i0.ɵɵelementEnd();
|
|
223
332
|
} if (rf & 2) {
|
|
224
|
-
const
|
|
225
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
226
|
-
i0.ɵɵclassProp("active", ctx_r1.recentRecordsEntityFilter ===
|
|
227
|
-
i0.ɵɵproperty("title",
|
|
333
|
+
const entity_r21 = ctx.$implicit;
|
|
334
|
+
const ctx_r1 = i0.ɵɵnextContext(7);
|
|
335
|
+
i0.ɵɵclassProp("active", ctx_r1.recentRecordsEntityFilter === entity_r21.entityId);
|
|
336
|
+
i0.ɵɵproperty("title", entity_r21.entityName);
|
|
228
337
|
i0.ɵɵadvance();
|
|
229
|
-
i0.ɵɵclassMap(
|
|
338
|
+
i0.ɵɵclassMap(entity_r21.icon);
|
|
230
339
|
} }
|
|
231
|
-
function
|
|
232
|
-
const
|
|
233
|
-
i0.ɵɵelementStart(0, "div",
|
|
234
|
-
i0.ɵɵlistener("click", function
|
|
235
|
-
i0.ɵɵelement(2, "i",
|
|
340
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
341
|
+
const _r19 = i0.ɵɵgetCurrentView();
|
|
342
|
+
i0.ɵɵelementStart(0, "div", 78)(1, "button", 81);
|
|
343
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Conditional_5_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.setRecentRecordsEntityFilter(null)); });
|
|
344
|
+
i0.ɵɵelement(2, "i", 82);
|
|
236
345
|
i0.ɵɵelementEnd();
|
|
237
|
-
i0.ɵɵrepeaterCreate(3,
|
|
346
|
+
i0.ɵɵrepeaterCreate(3, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Conditional_5_For_4_Template, 2, 5, "button", 83, _forTrack4);
|
|
238
347
|
i0.ɵɵelementEnd();
|
|
239
348
|
} if (rf & 2) {
|
|
240
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
349
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
241
350
|
i0.ɵɵadvance();
|
|
242
351
|
i0.ɵɵclassProp("active", ctx_r1.recentRecordsEntityFilter === null);
|
|
243
352
|
i0.ɵɵadvance(2);
|
|
244
353
|
i0.ɵɵrepeater(ctx_r1.uniqueRecentRecordEntities);
|
|
245
354
|
} }
|
|
246
|
-
function
|
|
247
|
-
const
|
|
248
|
-
i0.ɵɵelementStart(0, "div",
|
|
249
|
-
i0.ɵɵlistener("click", function
|
|
250
|
-
i0.ɵɵelementStart(1, "div",
|
|
355
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
356
|
+
const _r22 = i0.ɵɵgetCurrentView();
|
|
357
|
+
i0.ɵɵelementStart(0, "div", 85);
|
|
358
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_For_8_Template_div_click_0_listener() { const record_r23 = i0.ɵɵrestoreView(_r22).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.onRecentRecordClick(record_r23)); });
|
|
359
|
+
i0.ɵɵelementStart(1, "div", 86);
|
|
251
360
|
i0.ɵɵelement(2, "i");
|
|
252
361
|
i0.ɵɵelementEnd();
|
|
253
|
-
i0.ɵɵelementStart(3, "div",
|
|
362
|
+
i0.ɵɵelementStart(3, "div", 87)(4, "span", 88);
|
|
254
363
|
i0.ɵɵtext(5);
|
|
255
364
|
i0.ɵɵelementEnd();
|
|
256
|
-
i0.ɵɵelementStart(6, "span",
|
|
365
|
+
i0.ɵɵelementStart(6, "span", 89);
|
|
257
366
|
i0.ɵɵtext(7);
|
|
258
367
|
i0.ɵɵelementEnd()();
|
|
259
|
-
i0.ɵɵelementStart(8, "span",
|
|
368
|
+
i0.ɵɵelementStart(8, "span", 90);
|
|
260
369
|
i0.ɵɵtext(9);
|
|
261
370
|
i0.ɵɵelementEnd()();
|
|
262
371
|
} if (rf & 2) {
|
|
263
|
-
const
|
|
264
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
265
|
-
i0.ɵɵproperty("title",
|
|
372
|
+
const record_r23 = ctx.$implicit;
|
|
373
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
374
|
+
i0.ɵɵproperty("title", record_r23.entityName + " - " + record_r23.recordId);
|
|
266
375
|
i0.ɵɵadvance(2);
|
|
267
|
-
i0.ɵɵclassMap(ctx_r1.getEntityIconById(
|
|
376
|
+
i0.ɵɵclassMap(ctx_r1.getEntityIconById(record_r23.entityId));
|
|
268
377
|
i0.ɵɵadvance(3);
|
|
269
|
-
i0.ɵɵtextInterpolate(
|
|
378
|
+
i0.ɵɵtextInterpolate(record_r23.recordName || record_r23.recordId);
|
|
270
379
|
i0.ɵɵadvance(2);
|
|
271
|
-
i0.ɵɵtextInterpolate(
|
|
380
|
+
i0.ɵɵtextInterpolate(record_r23.entityName);
|
|
272
381
|
i0.ɵɵadvance(2);
|
|
273
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatRelativeTime(
|
|
382
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatRelativeTime(record_r23.latestAt));
|
|
274
383
|
} }
|
|
275
|
-
function
|
|
276
|
-
i0.ɵɵelementStart(0, "div",
|
|
277
|
-
i0.ɵɵelement(2, "i",
|
|
278
|
-
i0.ɵɵelementStart(3, "h3",
|
|
384
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
385
|
+
i0.ɵɵelementStart(0, "div", 61)(1, "div", 76);
|
|
386
|
+
i0.ɵɵelement(2, "i", 77);
|
|
387
|
+
i0.ɵɵelementStart(3, "h3", 67);
|
|
279
388
|
i0.ɵɵtext(4, "Recent Records");
|
|
280
389
|
i0.ɵɵelementEnd();
|
|
281
|
-
i0.ɵɵtemplate(5,
|
|
390
|
+
i0.ɵɵtemplate(5, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Conditional_5_Template, 5, 2, "div", 78);
|
|
282
391
|
i0.ɵɵelementEnd();
|
|
283
|
-
i0.ɵɵelementStart(6, "div",
|
|
284
|
-
i0.ɵɵrepeaterCreate(7,
|
|
392
|
+
i0.ɵɵelementStart(6, "div", 79);
|
|
393
|
+
i0.ɵɵrepeaterCreate(7, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_For_8_Template, 10, 6, "div", 80, _forTrack3);
|
|
285
394
|
i0.ɵɵelementEnd()();
|
|
286
395
|
} if (rf & 2) {
|
|
287
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
396
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
288
397
|
i0.ɵɵadvance(5);
|
|
289
398
|
i0.ɵɵconditional(ctx_r1.showRecentRecordsEntityFilter ? 5 : -1);
|
|
290
399
|
i0.ɵɵadvance(2);
|
|
291
400
|
i0.ɵɵrepeater(ctx_r1.filteredRecentRecords);
|
|
292
401
|
} }
|
|
293
|
-
function
|
|
294
|
-
const
|
|
295
|
-
i0.ɵɵelementStart(0, "div",
|
|
296
|
-
i0.ɵɵlistener("click", function
|
|
297
|
-
i0.ɵɵelementStart(1, "div",
|
|
402
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_2_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
403
|
+
const _r24 = i0.ɵɵgetCurrentView();
|
|
404
|
+
i0.ɵɵelementStart(0, "div", 85);
|
|
405
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_2_For_7_Template_div_click_0_listener() { const record_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.onFavoriteRecordClick(record_r25)); });
|
|
406
|
+
i0.ɵɵelementStart(1, "div", 86);
|
|
298
407
|
i0.ɵɵelement(2, "i");
|
|
299
408
|
i0.ɵɵelementEnd();
|
|
300
|
-
i0.ɵɵelementStart(3, "div",
|
|
409
|
+
i0.ɵɵelementStart(3, "div", 87)(4, "span", 88);
|
|
301
410
|
i0.ɵɵtext(5);
|
|
302
411
|
i0.ɵɵelementEnd();
|
|
303
|
-
i0.ɵɵelementStart(6, "span",
|
|
412
|
+
i0.ɵɵelementStart(6, "span", 89);
|
|
304
413
|
i0.ɵɵtext(7);
|
|
305
414
|
i0.ɵɵelementEnd()()();
|
|
306
415
|
} if (rf & 2) {
|
|
307
|
-
const
|
|
308
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
309
|
-
i0.ɵɵproperty("title",
|
|
416
|
+
const record_r25 = ctx.$implicit;
|
|
417
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
418
|
+
i0.ɵɵproperty("title", record_r25.entityName + " - " + record_r25.recordId);
|
|
310
419
|
i0.ɵɵadvance(2);
|
|
311
|
-
i0.ɵɵclassMap(ctx_r1.getEntityIconById(
|
|
420
|
+
i0.ɵɵclassMap(ctx_r1.getEntityIconById(record_r25.entityId));
|
|
312
421
|
i0.ɵɵadvance(3);
|
|
313
|
-
i0.ɵɵtextInterpolate(
|
|
422
|
+
i0.ɵɵtextInterpolate(record_r25.recordName || record_r25.recordId);
|
|
314
423
|
i0.ɵɵadvance(2);
|
|
315
|
-
i0.ɵɵtextInterpolate(
|
|
424
|
+
i0.ɵɵtextInterpolate(record_r25.entityName);
|
|
316
425
|
} }
|
|
317
|
-
function
|
|
318
|
-
i0.ɵɵelementStart(0, "div",
|
|
319
|
-
i0.ɵɵelement(2, "i",
|
|
320
|
-
i0.ɵɵelementStart(3, "h3",
|
|
426
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
427
|
+
i0.ɵɵelementStart(0, "div", 61)(1, "div", 76);
|
|
428
|
+
i0.ɵɵelement(2, "i", 91);
|
|
429
|
+
i0.ɵɵelementStart(3, "h3", 67);
|
|
321
430
|
i0.ɵɵtext(4, "Favorite Records");
|
|
322
431
|
i0.ɵɵelementEnd()();
|
|
323
|
-
i0.ɵɵelementStart(5, "div",
|
|
324
|
-
i0.ɵɵrepeaterCreate(6,
|
|
432
|
+
i0.ɵɵelementStart(5, "div", 79);
|
|
433
|
+
i0.ɵɵrepeaterCreate(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_2_For_7_Template, 8, 5, "div", 80, _forTrack5);
|
|
325
434
|
i0.ɵɵelementEnd()();
|
|
326
435
|
} if (rf & 2) {
|
|
327
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
436
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
328
437
|
i0.ɵɵadvance(6);
|
|
329
438
|
i0.ɵɵrepeater(ctx_r1.favoriteRecords);
|
|
330
439
|
} }
|
|
331
|
-
function
|
|
332
|
-
|
|
333
|
-
i0.ɵɵ
|
|
334
|
-
i0.ɵɵ
|
|
335
|
-
|
|
440
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
441
|
+
i0.ɵɵelementStart(0, "div", 75);
|
|
442
|
+
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_1_Template, 9, 1, "div", 61)(2, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Conditional_2_Template, 8, 0, "div", 61);
|
|
443
|
+
i0.ɵɵelementEnd();
|
|
444
|
+
} if (rf & 2) {
|
|
445
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
446
|
+
i0.ɵɵadvance();
|
|
447
|
+
i0.ɵɵconditional(ctx_r1.recentRecords.length > 0 ? 1 : -1);
|
|
448
|
+
i0.ɵɵadvance();
|
|
449
|
+
i0.ɵɵconditional(ctx_r1.favoriteRecords.length > 0 ? 2 : -1);
|
|
450
|
+
} }
|
|
451
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_1_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
452
|
+
const _r26 = i0.ɵɵgetCurrentView();
|
|
453
|
+
i0.ɵɵelementStart(0, "div", 95);
|
|
454
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_1_For_7_Template_div_click_0_listener() { const entity_r27 = i0.ɵɵrestoreView(_r26).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.onEntitySelected(entity_r27)); });
|
|
455
|
+
i0.ɵɵelementStart(1, "div", 96);
|
|
336
456
|
i0.ɵɵelement(2, "i");
|
|
337
457
|
i0.ɵɵelementEnd();
|
|
338
|
-
i0.ɵɵelementStart(3, "div",
|
|
458
|
+
i0.ɵɵelementStart(3, "div", 97)(4, "span", 98);
|
|
339
459
|
i0.ɵɵtext(5);
|
|
340
460
|
i0.ɵɵelementEnd()();
|
|
341
|
-
i0.ɵɵelementStart(6, "button",
|
|
342
|
-
i0.ɵɵlistener("click", function
|
|
461
|
+
i0.ɵɵelementStart(6, "button", 99);
|
|
462
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_1_For_7_Template_button_click_6_listener($event) { const entity_r27 = i0.ɵɵrestoreView(_r26).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.toggleEntityFavorite(entity_r27, $event)); });
|
|
343
463
|
i0.ɵɵelement(7, "i");
|
|
344
464
|
i0.ɵɵelementEnd()();
|
|
345
465
|
} if (rf & 2) {
|
|
346
|
-
const
|
|
347
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
348
|
-
i0.ɵɵproperty("title",
|
|
466
|
+
const entity_r27 = ctx.$implicit;
|
|
467
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
468
|
+
i0.ɵɵproperty("title", entity_r27.Description || entity_r27.Name);
|
|
349
469
|
i0.ɵɵadvance(2);
|
|
350
|
-
i0.ɵɵclassMap(ctx_r1.getEntityIcon(
|
|
470
|
+
i0.ɵɵclassMap(ctx_r1.getEntityIcon(entity_r27));
|
|
351
471
|
i0.ɵɵadvance(3);
|
|
352
|
-
i0.ɵɵtextInterpolate(
|
|
472
|
+
i0.ɵɵtextInterpolate(entity_r27.Name);
|
|
353
473
|
i0.ɵɵadvance();
|
|
354
|
-
i0.ɵɵclassProp("favorited", ctx_r1.isEntityFavorited(
|
|
355
|
-
i0.ɵɵproperty("title", ctx_r1.isEntityFavorited(
|
|
474
|
+
i0.ɵɵclassProp("favorited", ctx_r1.isEntityFavorited(entity_r27));
|
|
475
|
+
i0.ɵɵproperty("title", ctx_r1.isEntityFavorited(entity_r27) ? "Remove from favorites" : "Add to favorites");
|
|
356
476
|
i0.ɵɵadvance();
|
|
357
|
-
i0.ɵɵclassMap(ctx_r1.isEntityFavorited(
|
|
477
|
+
i0.ɵɵclassMap(ctx_r1.isEntityFavorited(entity_r27) ? "fa-solid fa-star" : "fa-regular fa-star");
|
|
358
478
|
} }
|
|
359
|
-
function
|
|
360
|
-
i0.ɵɵelementStart(0, "div",
|
|
361
|
-
i0.ɵɵelement(2, "i",
|
|
362
|
-
i0.ɵɵelementStart(3, "h3",
|
|
479
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
480
|
+
i0.ɵɵelementStart(0, "div", 61)(1, "div", 76);
|
|
481
|
+
i0.ɵɵelement(2, "i", 92);
|
|
482
|
+
i0.ɵɵelementStart(3, "h3", 67);
|
|
363
483
|
i0.ɵɵtext(4, "Recent Entities");
|
|
364
484
|
i0.ɵɵelementEnd()();
|
|
365
|
-
i0.ɵɵelementStart(5, "div",
|
|
366
|
-
i0.ɵɵrepeaterCreate(6,
|
|
485
|
+
i0.ɵɵelementStart(5, "div", 93);
|
|
486
|
+
i0.ɵɵrepeaterCreate(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_1_For_7_Template, 8, 9, "div", 94, _forTrack2);
|
|
367
487
|
i0.ɵɵelementEnd()();
|
|
368
488
|
} if (rf & 2) {
|
|
369
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
489
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
370
490
|
i0.ɵɵadvance(6);
|
|
371
491
|
i0.ɵɵrepeater(ctx_r1.recentEntities);
|
|
372
492
|
} }
|
|
373
|
-
function
|
|
374
|
-
const
|
|
375
|
-
i0.ɵɵelementStart(0, "div",
|
|
376
|
-
i0.ɵɵlistener("click", function
|
|
377
|
-
i0.ɵɵelementStart(1, "div",
|
|
493
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_2_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
494
|
+
const _r28 = i0.ɵɵgetCurrentView();
|
|
495
|
+
i0.ɵɵelementStart(0, "div", 95);
|
|
496
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_2_For_7_Template_div_click_0_listener() { const entity_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.onEntitySelected(entity_r29)); });
|
|
497
|
+
i0.ɵɵelementStart(1, "div", 96);
|
|
378
498
|
i0.ɵɵelement(2, "i");
|
|
379
499
|
i0.ɵɵelementEnd();
|
|
380
|
-
i0.ɵɵelementStart(3, "div",
|
|
500
|
+
i0.ɵɵelementStart(3, "div", 97)(4, "span", 98);
|
|
381
501
|
i0.ɵɵtext(5);
|
|
382
502
|
i0.ɵɵelementEnd()();
|
|
383
|
-
i0.ɵɵelementStart(6, "button",
|
|
384
|
-
i0.ɵɵlistener("click", function
|
|
385
|
-
i0.ɵɵelement(7, "i",
|
|
503
|
+
i0.ɵɵelementStart(6, "button", 100);
|
|
504
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_2_For_7_Template_button_click_6_listener($event) { const entity_r29 = i0.ɵɵrestoreView(_r28).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.toggleEntityFavorite(entity_r29, $event)); });
|
|
505
|
+
i0.ɵɵelement(7, "i", 101);
|
|
386
506
|
i0.ɵɵelementEnd()();
|
|
387
507
|
} if (rf & 2) {
|
|
388
|
-
const
|
|
389
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
390
|
-
i0.ɵɵproperty("title",
|
|
508
|
+
const entity_r29 = ctx.$implicit;
|
|
509
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
510
|
+
i0.ɵɵproperty("title", entity_r29.Description || entity_r29.Name);
|
|
391
511
|
i0.ɵɵadvance(2);
|
|
392
|
-
i0.ɵɵclassMap(ctx_r1.getEntityIcon(
|
|
512
|
+
i0.ɵɵclassMap(ctx_r1.getEntityIcon(entity_r29));
|
|
393
513
|
i0.ɵɵadvance(3);
|
|
394
|
-
i0.ɵɵtextInterpolate(
|
|
514
|
+
i0.ɵɵtextInterpolate(entity_r29.Name);
|
|
395
515
|
} }
|
|
396
|
-
function
|
|
397
|
-
i0.ɵɵelementStart(0, "div",
|
|
398
|
-
i0.ɵɵelement(2, "i",
|
|
399
|
-
i0.ɵɵelementStart(3, "h3",
|
|
516
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
517
|
+
i0.ɵɵelementStart(0, "div", 61)(1, "div", 76);
|
|
518
|
+
i0.ɵɵelement(2, "i", 91);
|
|
519
|
+
i0.ɵɵelementStart(3, "h3", 67);
|
|
400
520
|
i0.ɵɵtext(4, "Favorite Entities");
|
|
401
521
|
i0.ɵɵelementEnd()();
|
|
402
|
-
i0.ɵɵelementStart(5, "div",
|
|
403
|
-
i0.ɵɵrepeaterCreate(6,
|
|
522
|
+
i0.ɵɵelementStart(5, "div", 93);
|
|
523
|
+
i0.ɵɵrepeaterCreate(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_2_For_7_Template, 8, 4, "div", 94, _forTrack2);
|
|
404
524
|
i0.ɵɵelementEnd()();
|
|
405
525
|
} if (rf & 2) {
|
|
406
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
526
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
407
527
|
i0.ɵɵadvance(6);
|
|
408
528
|
i0.ɵɵrepeater(ctx_r1.favoriteEntities);
|
|
409
529
|
} }
|
|
530
|
+
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
531
|
+
i0.ɵɵelementStart(0, "div", 75);
|
|
532
|
+
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_1_Template, 8, 0, "div", 61)(2, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Conditional_2_Template, 8, 0, "div", 61);
|
|
533
|
+
i0.ɵɵelementEnd();
|
|
534
|
+
} if (rf & 2) {
|
|
535
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
536
|
+
i0.ɵɵadvance();
|
|
537
|
+
i0.ɵɵconditional(ctx_r1.recentEntities.length > 0 ? 1 : -1);
|
|
538
|
+
i0.ɵɵadvance();
|
|
539
|
+
i0.ɵɵconditional(ctx_r1.favoriteEntities.length > 0 ? 2 : -1);
|
|
540
|
+
} }
|
|
410
541
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
411
|
-
i0.ɵɵelementStart(0, "div",
|
|
412
|
-
i0.ɵɵtemplate(
|
|
542
|
+
i0.ɵɵelementStart(0, "div", 74);
|
|
543
|
+
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_1_Template, 3, 2, "div", 75)(2, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_2_Template, 3, 2, "div", 75);
|
|
413
544
|
i0.ɵɵelementEnd();
|
|
414
|
-
i0.ɵɵelementStart(4, "div", 52);
|
|
415
|
-
i0.ɵɵtemplate(5, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_5_Template, 8, 0, "div", 39)(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Conditional_6_Template, 8, 0, "div", 39);
|
|
416
|
-
i0.ɵɵelementEnd()();
|
|
417
545
|
} if (rf & 2) {
|
|
418
546
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
419
|
-
i0.ɵɵ
|
|
420
|
-
i0.ɵɵconditional(ctx_r1.recentRecords.length > 0 ? 2 : -1);
|
|
547
|
+
i0.ɵɵclassProp("single-column", !ctx_r1.hasRecordsColumnContent || !ctx_r1.hasEntitiesColumnContent);
|
|
421
548
|
i0.ɵɵadvance();
|
|
422
|
-
i0.ɵɵconditional(ctx_r1.
|
|
423
|
-
i0.ɵɵadvance(2);
|
|
424
|
-
i0.ɵɵconditional(ctx_r1.recentEntities.length > 0 ? 5 : -1);
|
|
549
|
+
i0.ɵɵconditional(ctx_r1.hasRecordsColumnContent ? 1 : -1);
|
|
425
550
|
i0.ɵɵadvance();
|
|
426
|
-
i0.ɵɵconditional(ctx_r1.
|
|
551
|
+
i0.ɵɵconditional(ctx_r1.hasEntitiesColumnContent ? 2 : -1);
|
|
427
552
|
} }
|
|
428
553
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
429
554
|
i0.ɵɵtext(0, " All Entities ");
|
|
@@ -432,7 +557,7 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional
|
|
|
432
557
|
i0.ɵɵtext(0, " Common Entities ");
|
|
433
558
|
} }
|
|
434
559
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
435
|
-
i0.ɵɵelementStart(0, "span",
|
|
560
|
+
i0.ɵɵelementStart(0, "span", 68);
|
|
436
561
|
i0.ɵɵtext(1);
|
|
437
562
|
i0.ɵɵelementEnd();
|
|
438
563
|
} if (rf & 2) {
|
|
@@ -441,13 +566,13 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional
|
|
|
441
566
|
i0.ɵɵtextInterpolate1("", ctx_r1.filteredEntities.length, " matching");
|
|
442
567
|
} }
|
|
443
568
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
444
|
-
const
|
|
445
|
-
i0.ɵɵelementStart(0, "div",
|
|
446
|
-
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template_button_click_1_listener() { i0.ɵɵrestoreView(
|
|
569
|
+
const _r30 = i0.ɵɵgetCurrentView();
|
|
570
|
+
i0.ɵɵelementStart(0, "div", 69)(1, "button", 51);
|
|
571
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleShowAllEntities()); });
|
|
447
572
|
i0.ɵɵtext(2, " Common ");
|
|
448
573
|
i0.ɵɵelementEnd();
|
|
449
|
-
i0.ɵɵelementStart(3, "button",
|
|
450
|
-
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template_button_click_3_listener() { i0.ɵɵrestoreView(
|
|
574
|
+
i0.ɵɵelementStart(3, "button", 51);
|
|
575
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleShowAllEntities()); });
|
|
451
576
|
i0.ɵɵtext(4, " All ");
|
|
452
577
|
i0.ɵɵelementEnd()();
|
|
453
578
|
} if (rf & 2) {
|
|
@@ -460,49 +585,49 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional
|
|
|
460
585
|
i0.ɵɵpropertyInterpolate1("title", "Show all entities (", ctx_r1.allEntitiesCount, ")");
|
|
461
586
|
} }
|
|
462
587
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
463
|
-
i0.ɵɵelementStart(0, "p",
|
|
588
|
+
i0.ɵɵelementStart(0, "p", 106);
|
|
464
589
|
i0.ɵɵtext(1);
|
|
465
590
|
i0.ɵɵelementEnd();
|
|
466
591
|
} if (rf & 2) {
|
|
467
|
-
const
|
|
592
|
+
const entity_r32 = i0.ɵɵnextContext().$implicit;
|
|
468
593
|
i0.ɵɵadvance();
|
|
469
|
-
i0.ɵɵtextInterpolate(
|
|
594
|
+
i0.ɵɵtextInterpolate(entity_r32.Description);
|
|
470
595
|
} }
|
|
471
596
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template(rf, ctx) { if (rf & 1) {
|
|
472
|
-
const
|
|
473
|
-
i0.ɵɵelementStart(0, "div",
|
|
474
|
-
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template_div_click_0_listener() { const
|
|
475
|
-
i0.ɵɵelementStart(1, "div",
|
|
597
|
+
const _r31 = i0.ɵɵgetCurrentView();
|
|
598
|
+
i0.ɵɵelementStart(0, "div", 102);
|
|
599
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template_div_click_0_listener() { const entity_r32 = i0.ɵɵrestoreView(_r31).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onEntitySelected(entity_r32)); });
|
|
600
|
+
i0.ɵɵelementStart(1, "div", 103);
|
|
476
601
|
i0.ɵɵelement(2, "i");
|
|
477
602
|
i0.ɵɵelementEnd();
|
|
478
|
-
i0.ɵɵelementStart(3, "div",
|
|
603
|
+
i0.ɵɵelementStart(3, "div", 104)(4, "h4", 105);
|
|
479
604
|
i0.ɵɵtext(5);
|
|
480
605
|
i0.ɵɵelementEnd();
|
|
481
|
-
i0.ɵɵtemplate(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Conditional_6_Template, 2, 1, "p",
|
|
606
|
+
i0.ɵɵtemplate(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Conditional_6_Template, 2, 1, "p", 106);
|
|
482
607
|
i0.ɵɵelementEnd();
|
|
483
|
-
i0.ɵɵelementStart(7, "button",
|
|
484
|
-
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template_button_click_7_listener($event) { const
|
|
608
|
+
i0.ɵɵelementStart(7, "button", 99);
|
|
609
|
+
i0.ɵɵlistener("click", function DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template_button_click_7_listener($event) { const entity_r32 = i0.ɵɵrestoreView(_r31).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleEntityFavorite(entity_r32, $event)); });
|
|
485
610
|
i0.ɵɵelement(8, "i");
|
|
486
611
|
i0.ɵɵelementEnd()();
|
|
487
612
|
} if (rf & 2) {
|
|
488
|
-
const
|
|
613
|
+
const entity_r32 = ctx.$implicit;
|
|
489
614
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
490
|
-
i0.ɵɵproperty("title",
|
|
615
|
+
i0.ɵɵproperty("title", entity_r32.Description || entity_r32.Name);
|
|
491
616
|
i0.ɵɵadvance(2);
|
|
492
|
-
i0.ɵɵclassMap(ctx_r1.getEntityIcon(
|
|
617
|
+
i0.ɵɵclassMap(ctx_r1.getEntityIcon(entity_r32));
|
|
493
618
|
i0.ɵɵadvance(3);
|
|
494
|
-
i0.ɵɵtextInterpolate(
|
|
619
|
+
i0.ɵɵtextInterpolate(entity_r32.Name);
|
|
495
620
|
i0.ɵɵadvance();
|
|
496
|
-
i0.ɵɵconditional(
|
|
621
|
+
i0.ɵɵconditional(entity_r32.Description ? 6 : -1);
|
|
497
622
|
i0.ɵɵadvance();
|
|
498
|
-
i0.ɵɵclassProp("favorited", ctx_r1.isEntityFavorited(
|
|
499
|
-
i0.ɵɵproperty("title", ctx_r1.isEntityFavorited(
|
|
623
|
+
i0.ɵɵclassProp("favorited", ctx_r1.isEntityFavorited(entity_r32));
|
|
624
|
+
i0.ɵɵproperty("title", ctx_r1.isEntityFavorited(entity_r32) ? "Remove from favorites" : "Add to favorites");
|
|
500
625
|
i0.ɵɵadvance();
|
|
501
|
-
i0.ɵɵclassMap(ctx_r1.isEntityFavorited(
|
|
626
|
+
i0.ɵɵclassMap(ctx_r1.isEntityFavorited(entity_r32) ? "fa-solid fa-star" : "fa-regular fa-star");
|
|
502
627
|
} }
|
|
503
628
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
504
|
-
i0.ɵɵelementStart(0, "div",
|
|
505
|
-
i0.ɵɵelement(1, "i",
|
|
629
|
+
i0.ɵɵelementStart(0, "div", 72);
|
|
630
|
+
i0.ɵɵelement(1, "i", 107);
|
|
506
631
|
i0.ɵɵelementStart(2, "h3");
|
|
507
632
|
i0.ɵɵtext(3, "No Matching Entities");
|
|
508
633
|
i0.ɵɵelementEnd();
|
|
@@ -515,8 +640,8 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional
|
|
|
515
640
|
i0.ɵɵtextInterpolate1("No entities match \"", ctx_r1.entityFilterText, "\"");
|
|
516
641
|
} }
|
|
517
642
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
518
|
-
i0.ɵɵelementStart(0, "div",
|
|
519
|
-
i0.ɵɵelement(1, "i",
|
|
643
|
+
i0.ɵɵelementStart(0, "div", 73);
|
|
644
|
+
i0.ɵɵelement(1, "i", 108);
|
|
520
645
|
i0.ɵɵelementStart(2, "h3");
|
|
521
646
|
i0.ɵɵtext(3, "No Entities Available");
|
|
522
647
|
i0.ɵɵelementEnd();
|
|
@@ -525,20 +650,20 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional
|
|
|
525
650
|
i0.ɵɵelementEnd()();
|
|
526
651
|
} }
|
|
527
652
|
function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
528
|
-
i0.ɵɵtemplate(0, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Template,
|
|
529
|
-
i0.ɵɵelementStart(1, "div",
|
|
530
|
-
i0.ɵɵelement(4, "i",
|
|
531
|
-
i0.ɵɵelementStart(5, "h3",
|
|
653
|
+
i0.ɵɵtemplate(0, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_0_Template, 3, 4, "div", 63);
|
|
654
|
+
i0.ɵɵelementStart(1, "div", 61)(2, "div", 64)(3, "div", 65);
|
|
655
|
+
i0.ɵɵelement(4, "i", 66);
|
|
656
|
+
i0.ɵɵelementStart(5, "h3", 67);
|
|
532
657
|
i0.ɵɵtemplate(6, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_6_Template, 1, 0)(7, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_7_Template, 1, 0);
|
|
533
658
|
i0.ɵɵelementEnd();
|
|
534
|
-
i0.ɵɵtemplate(8, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_8_Template, 2, 1, "span",
|
|
659
|
+
i0.ɵɵtemplate(8, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_8_Template, 2, 1, "span", 68);
|
|
535
660
|
i0.ɵɵelementEnd();
|
|
536
|
-
i0.ɵɵtemplate(9, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template, 5, 8, "div",
|
|
661
|
+
i0.ɵɵtemplate(9, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_9_Template, 5, 8, "div", 69);
|
|
537
662
|
i0.ɵɵelementEnd();
|
|
538
|
-
i0.ɵɵelementStart(10, "div",
|
|
539
|
-
i0.ɵɵrepeaterCreate(11, DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template, 9, 10, "div",
|
|
663
|
+
i0.ɵɵelementStart(10, "div", 70);
|
|
664
|
+
i0.ɵɵrepeaterCreate(11, DataExplorerDashboardComponent_Conditional_14_Conditional_2_For_12_Template, 9, 10, "div", 71, _forTrack2);
|
|
540
665
|
i0.ɵɵelementEnd();
|
|
541
|
-
i0.ɵɵtemplate(13, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_13_Template, 6, 1, "div",
|
|
666
|
+
i0.ɵɵtemplate(13, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_13_Template, 6, 1, "div", 72)(14, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Conditional_14_Template, 6, 0, "div", 73);
|
|
542
667
|
i0.ɵɵelementEnd();
|
|
543
668
|
} if (rf & 2) {
|
|
544
669
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -557,8 +682,8 @@ function DataExplorerDashboardComponent_Conditional_14_Conditional_2_Template(rf
|
|
|
557
682
|
i0.ɵɵconditional(ctx_r1.entities.length === 0 ? 14 : -1);
|
|
558
683
|
} }
|
|
559
684
|
function DataExplorerDashboardComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
560
|
-
i0.ɵɵelementStart(0, "div",
|
|
561
|
-
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_14_Conditional_1_Template, 2, 0, "div",
|
|
685
|
+
i0.ɵɵelementStart(0, "div", 11);
|
|
686
|
+
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_14_Conditional_1_Template, 2, 0, "div", 60)(2, DataExplorerDashboardComponent_Conditional_14_Conditional_2_Template, 15, 6, "div", 61);
|
|
562
687
|
i0.ɵɵelementEnd();
|
|
563
688
|
} if (rf & 2) {
|
|
564
689
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -566,18 +691,18 @@ function DataExplorerDashboardComponent_Conditional_14_Template(rf, ctx) { if (r
|
|
|
566
691
|
i0.ɵɵconditional(ctx_r1.isLoadingEntities ? 1 : 2);
|
|
567
692
|
} }
|
|
568
693
|
function DataExplorerDashboardComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
569
|
-
const
|
|
570
|
-
i0.ɵɵelementStart(0, "mj-entity-viewer",
|
|
571
|
-
i0.ɵɵlistener("viewModeChange", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_viewModeChange_0_listener($event) { i0.ɵɵrestoreView(
|
|
694
|
+
const _r33 = i0.ɵɵgetCurrentView();
|
|
695
|
+
i0.ɵɵelementStart(0, "mj-entity-viewer", 109);
|
|
696
|
+
i0.ɵɵlistener("viewModeChange", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_viewModeChange_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onViewModeChanged($event)); })("filterTextChange", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_filterTextChange_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onFilterTextChanged($event)); })("recordSelected", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_recordSelected_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onViewerRecordSelected($event)); })("recordOpened", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_recordOpened_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onViewerRecordOpened($event)); })("dataLoaded", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_dataLoaded_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDataLoaded($event)); })("filteredCountChanged", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_filteredCountChanged_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onFilteredCountChanged($event)); })("gridStateChanged", function DataExplorerDashboardComponent_Conditional_15_Template_mj_entity_viewer_gridStateChanged_0_listener($event) { i0.ɵɵrestoreView(_r33); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onGridStateChanged($event)); });
|
|
572
697
|
i0.ɵɵelementEnd();
|
|
573
698
|
} if (rf & 2) {
|
|
574
699
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
575
|
-
i0.ɵɵproperty("entity", ctx_r1.selectedEntity)("viewEntity", ctx_r1.selectedViewEntity)("viewMode", ctx_r1.state.viewMode)("filterText", ctx_r1.debouncedFilterText)("selectedRecordId", ctx_r1.state.selectedRecordId)("config", ctx_r1.viewerConfig)("gridState", ctx_r1.currentGridState);
|
|
700
|
+
i0.ɵɵproperty("entity", ctx_r1.selectedEntity)("viewEntity", ctx_r1.selectedViewEntity)("viewMode", ctx_r1.state.viewMode)("filterText", ctx_r1.debouncedFilterText)("selectedRecordId", ctx_r1.state.selectedRecordId)("config", ctx_r1.viewerConfig)("gridState", ctx_r1.currentGridState)("timelineConfig", ctx_r1.currentTimelineConfig);
|
|
576
701
|
} }
|
|
577
702
|
function DataExplorerDashboardComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
578
|
-
const
|
|
579
|
-
i0.ɵɵelementStart(0, "div",
|
|
580
|
-
i0.ɵɵlistener("close", function DataExplorerDashboardComponent_Conditional_16_Template_mj_entity_record_detail_panel_close_1_listener() { i0.ɵɵrestoreView(
|
|
703
|
+
const _r34 = i0.ɵɵgetCurrentView();
|
|
704
|
+
i0.ɵɵelementStart(0, "div", 110)(1, "mj-entity-record-detail-panel", 111);
|
|
705
|
+
i0.ɵɵlistener("close", function DataExplorerDashboardComponent_Conditional_16_Template_mj_entity_record_detail_panel_close_1_listener() { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDetailPanelClosed()); })("openRecord", function DataExplorerDashboardComponent_Conditional_16_Template_mj_entity_record_detail_panel_openRecord_1_listener($event) { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onOpenRecord($event)); })("navigateToRelated", function DataExplorerDashboardComponent_Conditional_16_Template_mj_entity_record_detail_panel_navigateToRelated_1_listener($event) { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onNavigateToRelated($event)); })("openRelatedRecord", function DataExplorerDashboardComponent_Conditional_16_Template_mj_entity_record_detail_panel_openRelatedRecord_1_listener($event) { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onOpenRelatedRecord($event)); })("openForeignKeyRecord", function DataExplorerDashboardComponent_Conditional_16_Template_mj_entity_record_detail_panel_openForeignKeyRecord_1_listener($event) { i0.ɵɵrestoreView(_r34); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onOpenForeignKeyRecord($event)); });
|
|
581
706
|
i0.ɵɵelementEnd()();
|
|
582
707
|
} if (rf & 2) {
|
|
583
708
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -597,6 +722,7 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
597
722
|
cdr;
|
|
598
723
|
router;
|
|
599
724
|
recentAccessService;
|
|
725
|
+
navigationService;
|
|
600
726
|
destroy$ = new Subject();
|
|
601
727
|
metadata = new Metadata();
|
|
602
728
|
/** Reference to the filter input for keyboard shortcuts */
|
|
@@ -605,6 +731,8 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
605
731
|
viewSelectorRef;
|
|
606
732
|
/** Reference to the entity viewer for refreshing after view save */
|
|
607
733
|
entityViewerRef;
|
|
734
|
+
/** Reference to the view config panel for passing filter state */
|
|
735
|
+
viewConfigPanelRef;
|
|
608
736
|
/**
|
|
609
737
|
* Optional filter to constrain which entities are shown in the explorer.
|
|
610
738
|
* Can filter by applicationId, schemaNames, or explicit entityNames.
|
|
@@ -654,6 +782,8 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
654
782
|
breadcrumbs = [];
|
|
655
783
|
// Loading state for entities
|
|
656
784
|
isLoadingEntities = true;
|
|
785
|
+
// Date field dropdown state
|
|
786
|
+
isDateFieldDropdownOpen = false;
|
|
657
787
|
// Flag to skip URL updates during initialization (when applying deep link)
|
|
658
788
|
skipUrlUpdates = true;
|
|
659
789
|
// Track the last URL we navigated to, to avoid reacting to our own navigation
|
|
@@ -742,6 +872,18 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
742
872
|
this.recentRecords.length > 0 ||
|
|
743
873
|
this.favoriteRecords.length > 0;
|
|
744
874
|
}
|
|
875
|
+
/**
|
|
876
|
+
* Check if the left column (records column) has content
|
|
877
|
+
*/
|
|
878
|
+
get hasRecordsColumnContent() {
|
|
879
|
+
return this.recentRecords.length > 0 || this.favoriteRecords.length > 0;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Check if the right column (entities column) has content
|
|
883
|
+
*/
|
|
884
|
+
get hasEntitiesColumnContent() {
|
|
885
|
+
return this.recentEntities.length > 0 || this.favoriteEntities.length > 0;
|
|
886
|
+
}
|
|
745
887
|
/**
|
|
746
888
|
* Get unique entities from recent records for the filter strip.
|
|
747
889
|
* Returns up to 5 entities, sorted by frequency in the recent records.
|
|
@@ -806,6 +948,114 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
806
948
|
get displayIcon() {
|
|
807
949
|
return this.contextIcon;
|
|
808
950
|
}
|
|
951
|
+
/**
|
|
952
|
+
* Check if the currently selected entity has date fields available for timeline view.
|
|
953
|
+
* Used to conditionally show the timeline toggle button in the header.
|
|
954
|
+
*/
|
|
955
|
+
get entityHasDateFields() {
|
|
956
|
+
if (!this.selectedEntity)
|
|
957
|
+
return false;
|
|
958
|
+
return this.selectedEntity.Fields.some(f => f.TSType === EntityFieldTSType.Date);
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Get available date fields for the currently selected entity.
|
|
962
|
+
* Used for the date field selector in timeline view.
|
|
963
|
+
*/
|
|
964
|
+
get availableDateFields() {
|
|
965
|
+
if (!this.selectedEntity)
|
|
966
|
+
return [];
|
|
967
|
+
return this.selectedEntity.Fields
|
|
968
|
+
.filter(f => f.TSType === EntityFieldTSType.Date)
|
|
969
|
+
.sort((a, b) => {
|
|
970
|
+
// Prioritize DefaultInView fields, then by Sequence
|
|
971
|
+
if (a.DefaultInView && !b.DefaultInView)
|
|
972
|
+
return -1;
|
|
973
|
+
if (!a.DefaultInView && b.DefaultInView)
|
|
974
|
+
return 1;
|
|
975
|
+
return a.Sequence - b.Sequence;
|
|
976
|
+
})
|
|
977
|
+
.map(f => ({
|
|
978
|
+
name: f.Name,
|
|
979
|
+
displayName: f.DisplayNameOrName
|
|
980
|
+
}));
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Get the effective timeline date field name.
|
|
984
|
+
* Returns stored value if valid, otherwise first available date field.
|
|
985
|
+
*/
|
|
986
|
+
get effectiveTimelineDateField() {
|
|
987
|
+
const available = this.availableDateFields;
|
|
988
|
+
if (available.length === 0)
|
|
989
|
+
return null;
|
|
990
|
+
// Check if stored value is still valid
|
|
991
|
+
if (this.state.timelineDateFieldName && available.some(f => f.name === this.state.timelineDateFieldName)) {
|
|
992
|
+
return this.state.timelineDateFieldName;
|
|
993
|
+
}
|
|
994
|
+
// Default to first available
|
|
995
|
+
return available[0].name;
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Get the display name of the effective timeline date field.
|
|
999
|
+
*/
|
|
1000
|
+
get effectiveTimelineDateFieldDisplayName() {
|
|
1001
|
+
const fieldName = this.effectiveTimelineDateField;
|
|
1002
|
+
if (!fieldName)
|
|
1003
|
+
return '';
|
|
1004
|
+
const field = this.availableDateFields.find(f => f.name === fieldName);
|
|
1005
|
+
return field?.displayName || fieldName;
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Set the timeline date field.
|
|
1009
|
+
*/
|
|
1010
|
+
setTimelineDateField(fieldName) {
|
|
1011
|
+
this.state.timelineDateFieldName = fieldName;
|
|
1012
|
+
this.stateService.updateState({ timelineDateFieldName: fieldName });
|
|
1013
|
+
this.isDateFieldDropdownOpen = false;
|
|
1014
|
+
this.cdr.detectChanges();
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Toggle the date field dropdown open/closed.
|
|
1018
|
+
*/
|
|
1019
|
+
toggleDateFieldDropdown() {
|
|
1020
|
+
this.isDateFieldDropdownOpen = !this.isDateFieldDropdownOpen;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Close the date field dropdown.
|
|
1024
|
+
*/
|
|
1025
|
+
closeDateFieldDropdown() {
|
|
1026
|
+
this.isDateFieldDropdownOpen = false;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Toggle timeline orientation between vertical and horizontal.
|
|
1030
|
+
*/
|
|
1031
|
+
toggleTimelineOrientation() {
|
|
1032
|
+
const newOrientation = this.state.timelineOrientation === 'vertical' ? 'horizontal' : 'vertical';
|
|
1033
|
+
this.state.timelineOrientation = newOrientation;
|
|
1034
|
+
this.stateService.updateState({ timelineOrientation: newOrientation });
|
|
1035
|
+
this.cdr.detectChanges();
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Toggle timeline sort order between newest first (desc) and oldest first (asc).
|
|
1039
|
+
*/
|
|
1040
|
+
toggleTimelineSortOrder() {
|
|
1041
|
+
const newSortOrder = this.state.timelineSortOrder === 'desc' ? 'asc' : 'desc';
|
|
1042
|
+
this.state.timelineSortOrder = newSortOrder;
|
|
1043
|
+
this.stateService.updateState({ timelineSortOrder: newSortOrder });
|
|
1044
|
+
this.cdr.detectChanges();
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Get the current timeline configuration for the entity-viewer.
|
|
1048
|
+
*/
|
|
1049
|
+
get currentTimelineConfig() {
|
|
1050
|
+
const dateField = this.effectiveTimelineDateField;
|
|
1051
|
+
if (!dateField)
|
|
1052
|
+
return null;
|
|
1053
|
+
return {
|
|
1054
|
+
dateFieldName: dateField,
|
|
1055
|
+
orientation: this.state.timelineOrientation,
|
|
1056
|
+
sortOrder: this.state.timelineSortOrder
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
809
1059
|
/**
|
|
810
1060
|
* Configuration for mj-entity-viewer composite component
|
|
811
1061
|
* Hides the built-in header since we have a custom header in the dashboard
|
|
@@ -825,12 +1075,18 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
825
1075
|
* This is passed to mj-entity-viewer to control column display
|
|
826
1076
|
*/
|
|
827
1077
|
currentGridState = null;
|
|
828
|
-
|
|
1078
|
+
// Filter dialog state (rendered at dashboard level for full viewport width)
|
|
1079
|
+
isFilterDialogOpen = false;
|
|
1080
|
+
filterDialogFields = [];
|
|
1081
|
+
filterDialogState = createEmptyFilter();
|
|
1082
|
+
filterDialogDisabled = false;
|
|
1083
|
+
constructor(stateService, cdr, router, recentAccessService, navigationService) {
|
|
829
1084
|
super();
|
|
830
1085
|
this.stateService = stateService;
|
|
831
1086
|
this.cdr = cdr;
|
|
832
1087
|
this.router = router;
|
|
833
1088
|
this.recentAccessService = recentAccessService;
|
|
1089
|
+
this.navigationService = navigationService;
|
|
834
1090
|
this.state = this.stateService.CurrentState;
|
|
835
1091
|
}
|
|
836
1092
|
async ngOnInit() {
|
|
@@ -984,7 +1240,6 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
984
1240
|
* @param urlState Optional URL state - if provided, skip restoring persisted entity to avoid race conditions
|
|
985
1241
|
*/
|
|
986
1242
|
async loadEntities(urlState) {
|
|
987
|
-
console.log('[DataExplorer] loadEntities called, entityFilter:', this.entityFilter);
|
|
988
1243
|
this.isLoadingEntities = true;
|
|
989
1244
|
try {
|
|
990
1245
|
// First, load all entities the user can access
|
|
@@ -994,15 +1249,12 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
994
1249
|
return perms.CanRead && e.IncludeInAPI;
|
|
995
1250
|
})
|
|
996
1251
|
.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
997
|
-
console.log('[DataExplorer] allEntities count:', this.allEntities.length);
|
|
998
1252
|
// If we have an applicationId filter, load the application entities
|
|
999
1253
|
if (this.entityFilter?.applicationId) {
|
|
1000
1254
|
await this.loadApplicationEntityIds(this.entityFilter.applicationId);
|
|
1001
|
-
console.log('[DataExplorer] applicationEntityIds count:', this.applicationEntityIds.size);
|
|
1002
1255
|
}
|
|
1003
1256
|
// Apply filter to get the final entity list
|
|
1004
1257
|
this.entities = this.applyEntityFilter(this.allEntities);
|
|
1005
|
-
console.log('[DataExplorer] filtered entities count:', this.entities.length);
|
|
1006
1258
|
// Only restore entity from persisted state if there's no URL state
|
|
1007
1259
|
// This prevents race conditions where persisted entity triggers data load
|
|
1008
1260
|
// before URL state can override it
|
|
@@ -1075,6 +1327,9 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1075
1327
|
onEntitySelected(entity) {
|
|
1076
1328
|
this.resetRecordCounts();
|
|
1077
1329
|
this.selectedEntity = entity;
|
|
1330
|
+
// Reset grid state when entity changes - grid state is entity-specific
|
|
1331
|
+
// Without this, columns from a previously viewed entity would incorrectly apply
|
|
1332
|
+
this.currentGridState = null;
|
|
1078
1333
|
this.stateService.selectEntity(entity.Name);
|
|
1079
1334
|
// Track entity access for recent entities
|
|
1080
1335
|
this.stateService.trackEntityAccess(entity.Name, entity.ID);
|
|
@@ -1086,6 +1341,8 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1086
1341
|
onStateChanged() {
|
|
1087
1342
|
if (this.state.selectedEntityName !== this.selectedEntity?.Name) {
|
|
1088
1343
|
this.resetRecordCounts();
|
|
1344
|
+
// Reset grid state when entity changes - grid state is entity-specific
|
|
1345
|
+
this.currentGridState = null;
|
|
1089
1346
|
this.selectedEntity = this.entities.find(e => e.Name === this.state.selectedEntityName) || null;
|
|
1090
1347
|
}
|
|
1091
1348
|
}
|
|
@@ -1177,21 +1434,15 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1177
1434
|
*/
|
|
1178
1435
|
onManageViewsRequested() {
|
|
1179
1436
|
// TODO: Implement navigation to view management
|
|
1180
|
-
// For now, just log
|
|
1181
|
-
console.log('[DataExplorer] Manage views requested');
|
|
1182
1437
|
}
|
|
1183
1438
|
/**
|
|
1184
|
-
* Handle open in tab request
|
|
1439
|
+
* Handle open in tab request - opens the view as a ViewResource in a new tab
|
|
1185
1440
|
*/
|
|
1186
1441
|
onOpenInTabRequested(viewId) {
|
|
1187
|
-
//
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
this.OpenEntityRecord.emit({
|
|
1192
|
-
EntityName: 'User Views',
|
|
1193
|
-
RecordPKey: compositeKey
|
|
1194
|
-
});
|
|
1442
|
+
// Get the view name from the component's selectedViewEntity (set when view is selected)
|
|
1443
|
+
const viewName = this.selectedViewEntity?.Name || 'View';
|
|
1444
|
+
// Use NavigationService to open as a proper ViewResource (not entity record)
|
|
1445
|
+
this.navigationService.OpenView(viewId, viewName, { forceNewTab: true });
|
|
1195
1446
|
}
|
|
1196
1447
|
/**
|
|
1197
1448
|
* Handle configure view request - opens the configuration panel
|
|
@@ -1205,6 +1456,36 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1205
1456
|
onCloseViewConfigPanel() {
|
|
1206
1457
|
this.stateService.closeViewConfigPanel();
|
|
1207
1458
|
}
|
|
1459
|
+
// ========================================
|
|
1460
|
+
// FILTER DIALOG (at dashboard level for full width)
|
|
1461
|
+
// ========================================
|
|
1462
|
+
/**
|
|
1463
|
+
* Handle request to open filter dialog from view config panel
|
|
1464
|
+
* The dialog is rendered at dashboard level to allow full viewport width
|
|
1465
|
+
*/
|
|
1466
|
+
onOpenFilterDialogRequest(event) {
|
|
1467
|
+
this.filterDialogState = event.filterState;
|
|
1468
|
+
this.filterDialogFields = event.filterFields;
|
|
1469
|
+
this.filterDialogDisabled = !this.viewConfigPanelRef?.canEdit;
|
|
1470
|
+
this.isFilterDialogOpen = true;
|
|
1471
|
+
this.cdr.detectChanges();
|
|
1472
|
+
}
|
|
1473
|
+
/**
|
|
1474
|
+
* Close the filter dialog
|
|
1475
|
+
*/
|
|
1476
|
+
onCloseFilterDialog() {
|
|
1477
|
+
this.isFilterDialogOpen = false;
|
|
1478
|
+
this.cdr.detectChanges();
|
|
1479
|
+
}
|
|
1480
|
+
/**
|
|
1481
|
+
* Handle filter applied from dialog - pass back to view config panel
|
|
1482
|
+
*/
|
|
1483
|
+
onFilterApplied(filter) {
|
|
1484
|
+
this.filterDialogState = filter;
|
|
1485
|
+
this.isFilterDialogOpen = false;
|
|
1486
|
+
// The view config panel will pick up the new filter state via input binding
|
|
1487
|
+
this.cdr.detectChanges();
|
|
1488
|
+
}
|
|
1208
1489
|
/**
|
|
1209
1490
|
* Handle save view from config panel
|
|
1210
1491
|
*/
|
|
@@ -1236,6 +1517,11 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1236
1517
|
// Set Smart Filter settings
|
|
1237
1518
|
newView.SmartFilterEnabled = event.smartFilterEnabled;
|
|
1238
1519
|
newView.SmartFilterPrompt = event.smartFilterPrompt;
|
|
1520
|
+
// Set traditional filter state (Kendo-compatible JSON format)
|
|
1521
|
+
// The UserViewEntity.Save() will auto-generate WhereClause from FilterState
|
|
1522
|
+
if (event.filterState) {
|
|
1523
|
+
newView.FilterState = JSON.stringify(event.filterState);
|
|
1524
|
+
}
|
|
1239
1525
|
const saved = await newView.Save();
|
|
1240
1526
|
if (saved) {
|
|
1241
1527
|
this.selectedViewEntity = newView;
|
|
@@ -1264,6 +1550,15 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1264
1550
|
// Update Smart Filter settings
|
|
1265
1551
|
this.selectedViewEntity.SmartFilterEnabled = event.smartFilterEnabled;
|
|
1266
1552
|
this.selectedViewEntity.SmartFilterPrompt = event.smartFilterPrompt;
|
|
1553
|
+
// Update traditional filter state (Kendo-compatible JSON format)
|
|
1554
|
+
// The UserViewEntity.Save() will auto-generate WhereClause from FilterState
|
|
1555
|
+
if (event.filterState) {
|
|
1556
|
+
this.selectedViewEntity.FilterState = JSON.stringify(event.filterState);
|
|
1557
|
+
}
|
|
1558
|
+
else {
|
|
1559
|
+
// Clear filter state if no filters
|
|
1560
|
+
this.selectedViewEntity.FilterState = JSON.stringify({ logic: 'and', filters: [] });
|
|
1561
|
+
}
|
|
1267
1562
|
const saved = await this.selectedViewEntity.Save();
|
|
1268
1563
|
if (saved) {
|
|
1269
1564
|
this.stateService.setViewModified(false);
|
|
@@ -1273,7 +1568,10 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
1273
1568
|
this.cdr.detectChanges();
|
|
1274
1569
|
// Refresh the view selector dropdown
|
|
1275
1570
|
await this.viewSelectorRef?.loadViews();
|
|
1276
|
-
//
|
|
1571
|
+
// Refresh the entity viewer data to apply saved filters/sorts
|
|
1572
|
+
// Note: viewEntity reference didn't change, so we need to manually trigger refresh
|
|
1573
|
+
// Use refresh() instead of loadData() to reset pagination state and reload from page 1
|
|
1574
|
+
this.entityViewerRef?.refresh();
|
|
1277
1575
|
}
|
|
1278
1576
|
}
|
|
1279
1577
|
this.stateService.closeViewConfigPanel();
|
|
@@ -2015,19 +2313,21 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
2015
2313
|
get isAtHomeLevel() {
|
|
2016
2314
|
return !this.selectedEntity;
|
|
2017
2315
|
}
|
|
2018
|
-
static ɵfac = function DataExplorerDashboardComponent_Factory(t) { return new (t || DataExplorerDashboardComponent)(i0.ɵɵdirectiveInject(i1.ExplorerStateService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i3.RecentAccessService)); };
|
|
2316
|
+
static ɵfac = function DataExplorerDashboardComponent_Factory(t) { return new (t || DataExplorerDashboardComponent)(i0.ɵɵdirectiveInject(i1.ExplorerStateService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i2.Router), i0.ɵɵdirectiveInject(i3.RecentAccessService), i0.ɵɵdirectiveInject(i4.NavigationService)); };
|
|
2019
2317
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DataExplorerDashboardComponent, selectors: [["mj-data-explorer-dashboard"]], viewQuery: function DataExplorerDashboardComponent_Query(rf, ctx) { if (rf & 1) {
|
|
2020
2318
|
i0.ɵɵviewQuery(_c0, 5);
|
|
2021
2319
|
i0.ɵɵviewQuery(ViewSelectorComponent, 5);
|
|
2022
2320
|
i0.ɵɵviewQuery(EntityViewerComponent, 5);
|
|
2321
|
+
i0.ɵɵviewQuery(ViewConfigPanelComponent, 5);
|
|
2023
2322
|
} if (rf & 2) {
|
|
2024
2323
|
let _t;
|
|
2025
2324
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.filterInputRef = _t.first);
|
|
2026
2325
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.viewSelectorRef = _t.first);
|
|
2027
2326
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.entityViewerRef = _t.first);
|
|
2327
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.viewConfigPanelRef = _t.first);
|
|
2028
2328
|
} }, hostBindings: function DataExplorerDashboardComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
2029
2329
|
i0.ɵɵlistener("keydown", function DataExplorerDashboardComponent_keydown_HostBindingHandler($event) { return ctx.handleKeyboardShortcut($event); }, false, i0.ɵɵresolveDocument);
|
|
2030
|
-
} }, inputs: { entityFilter: "entityFilter", deepLink: "deepLink", contextName: "contextName", contextIcon: "contextIcon" }, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls:
|
|
2330
|
+
} }, inputs: { entityFilter: "entityFilter", deepLink: "deepLink", contextName: "contextName", contextIcon: "contextIcon" }, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 19, vars: 20, consts: [["filterInput", ""], [1, "data-explorer-container"], [1, "navigation-panel", 3, "collapsed", "width"], [1, "content-area"], [1, "breadcrumb-bar"], [1, "content-header"], [1, "header-left"], [1, "header-center"], [1, "smart-filter-container"], [1, "header-right"], [1, "content-body"], [1, "entity-home-view"], [3, "entity", "viewEntity", "viewMode", "filterText", "selectedRecordId", "config", "gridState", "timelineConfig"], [1, "detail-panel", 3, "width"], [3, "close", "save", "delete", "openFilterDialogRequest", "entity", "viewEntity", "isOpen", "currentGridState", "externalFilterState"], [3, "close", "apply", "isOpen", "fields", "filter", "disabled"], [1, "navigation-panel"], [3, "entitySelected", "toggleCollapse", "sectionToggled", "openRecord", "selectRecord", "expandAndFocus", "entities", "selectedEntityName", "favorites", "recentItems", "collapsed", "allowedEntityNames", "favoritesSectionExpanded", "recentSectionExpanded", "entitiesSectionExpanded", "viewsSectionExpanded"], [1, "breadcrumb-item", 3, "click", "title"], [1, "breadcrumb-icon", 3, "class"], [1, "breadcrumb-label"], [1, "fa-solid", "fa-chevron-right", "breadcrumb-separator"], [1, "breadcrumb-icon"], [1, "entity-icon"], [1, "entity-title"], [1, "record-count"], [3, "viewSelected", "saveViewRequested", "manageViewsRequested", "openInTabRequested", "configureViewRequested", "entity", "selectedViewId", "viewModified"], [1, "entity-icon", 3, "class"], [1, "fa-solid", "fa-search", "filter-icon"], ["type", "text", "placeholder", "Filter records... (press / to focus)", 1, "smart-filter-input", 3, "ngModelChange", "ngModel"], [1, "clear-filter-btn"], [1, "clear-filter-btn", 3, "click"], [1, "fa-solid", "fa-times"], ["type", "text", "placeholder", "Filter entities... (press / to focus)", 1, "smart-filter-input", 3, "ngModelChange", "ngModel"], [1, "view-mode-toggle"], ["title", "Grid View", 1, "toggle-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Cards View", 1, "toggle-btn", 3, "click"], [1, "fa-solid", "fa-grip"], ["title", "Timeline View", 1, "toggle-btn", 3, "active"], ["title", "Timeline View", 1, "toggle-btn", 3, "click"], [1, "fa-solid", "fa-timeline"], [1, "date-field-selector-container"], [1, "date-field-backdrop"], [1, "date-field-selector-wrapper"], [1, "date-field-selector-button", 3, "click", "disabled"], [1, "fa-solid", "fa-calendar-days", "date-field-icon"], [1, "date-field-name"], [1, "fa-solid", "fa-chevron-down", "date-field-arrow", 3, "rotated"], [1, "date-field-dropdown-panel"], [1, "timeline-orientation-toggle"], [1, "toggle-btn", 3, "click", "title"], [1, "timeline-sort-toggle"], [1, "date-field-backdrop", 3, "click"], [1, "fa-solid", "fa-chevron-down", "date-field-arrow"], [1, "date-field-dropdown-item", 3, "selected"], [1, "date-field-dropdown-item", 3, "click"], [1, "fa-regular", "fa-calendar", "item-icon"], [1, "item-name"], [1, "fa-solid", "fa-check", "selected-check"], [1, "loading-state"], [1, "home-section"], ["text", "Loading entities...", "size", "medium"], [1, "home-two-column-layout", 3, "single-column"], [1, "section-header-with-toggle"], [1, "section-header-left"], [1, "fa-solid", "fa-database", "section-icon"], [1, "section-title"], [1, "section-count"], [1, "inline-toggle"], [1, "entity-card-grid"], [1, "entity-card", 3, "title"], [1, "empty-state", "small"], [1, "empty-state"], [1, "home-two-column-layout"], [1, "home-column"], [1, "section-header"], [1, "fa-solid", "fa-history", "section-icon"], [1, "entity-filter-strip"], [1, "recent-records-list"], [1, "recent-record-item", 3, "title"], ["title", "Show all entities", 1, "entity-filter-btn", 3, "click"], [1, "fa-solid", "fa-layer-group"], [1, "entity-filter-btn", 3, "active", "title"], [1, "entity-filter-btn", 3, "click", "title"], [1, "recent-record-item", 3, "click", "title"], [1, "recent-record-icon"], [1, "recent-record-content"], [1, "recent-record-name"], [1, "recent-record-entity"], [1, "recent-record-time"], [1, "fa-solid", "fa-star", "section-icon"], [1, "fa-solid", "fa-clock", "section-icon"], [1, "entity-list"], [1, "entity-list-item", 3, "title"], [1, "entity-list-item", 3, "click", "title"], [1, "entity-list-icon"], [1, "entity-list-content"], [1, "entity-list-name"], [1, "favorite-btn", 3, "click", "title"], ["title", "Remove from favorites", 1, "favorite-btn", "favorited", 3, "click"], [1, "fa-solid", "fa-star"], [1, "entity-card", 3, "click", "title"], [1, "entity-card-icon"], [1, "entity-card-content"], [1, "entity-card-title"], [1, "entity-card-description"], [1, "fa-solid", "fa-search", "empty-icon"], [1, "fa-solid", "fa-database", "empty-icon"], [3, "viewModeChange", "filterTextChange", "recordSelected", "recordOpened", "dataLoaded", "filteredCountChanged", "gridStateChanged", "entity", "viewEntity", "viewMode", "filterText", "selectedRecordId", "config", "gridState", "timelineConfig"], [1, "detail-panel"], [3, "close", "openRecord", "navigateToRelated", "openRelatedRecord", "openForeignKeyRecord", "entity", "record"]], template: function DataExplorerDashboardComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2031
2331
|
i0.ɵɵelementStart(0, "div", 1);
|
|
2032
2332
|
i0.ɵɵtemplate(1, DataExplorerDashboardComponent_Conditional_1_Template, 2, 15, "div", 2);
|
|
2033
2333
|
i0.ɵɵelementStart(2, "div", 3);
|
|
@@ -2039,14 +2339,17 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
2039
2339
|
i0.ɵɵtemplate(9, DataExplorerDashboardComponent_Conditional_9_Template, 5, 2, "div", 8)(10, DataExplorerDashboardComponent_Conditional_10_Template, 5, 2, "div", 8);
|
|
2040
2340
|
i0.ɵɵelementEnd();
|
|
2041
2341
|
i0.ɵɵelementStart(11, "div", 9);
|
|
2042
|
-
i0.ɵɵtemplate(12, DataExplorerDashboardComponent_Conditional_12_Template,
|
|
2342
|
+
i0.ɵɵtemplate(12, DataExplorerDashboardComponent_Conditional_12_Template, 7, 6);
|
|
2043
2343
|
i0.ɵɵelementEnd()();
|
|
2044
|
-
i0.ɵɵelementStart(13, "div",
|
|
2045
|
-
i0.ɵɵtemplate(14, DataExplorerDashboardComponent_Conditional_14_Template, 3, 1, "div",
|
|
2344
|
+
i0.ɵɵelementStart(13, "div", 10);
|
|
2345
|
+
i0.ɵɵtemplate(14, DataExplorerDashboardComponent_Conditional_14_Template, 3, 1, "div", 11)(15, DataExplorerDashboardComponent_Conditional_15_Template, 1, 8, "mj-entity-viewer", 12);
|
|
2046
2346
|
i0.ɵɵelementEnd()();
|
|
2047
|
-
i0.ɵɵtemplate(16, DataExplorerDashboardComponent_Conditional_16_Template, 2, 4, "div",
|
|
2048
|
-
i0.ɵɵelementStart(17, "mj-view-config-panel",
|
|
2049
|
-
i0.ɵɵlistener("close", function DataExplorerDashboardComponent_Template_mj_view_config_panel_close_17_listener() { return ctx.onCloseViewConfigPanel(); })("save", function DataExplorerDashboardComponent_Template_mj_view_config_panel_save_17_listener($event) { return ctx.onSaveView($event); })("delete", function DataExplorerDashboardComponent_Template_mj_view_config_panel_delete_17_listener() { return ctx.onDeleteView(); });
|
|
2347
|
+
i0.ɵɵtemplate(16, DataExplorerDashboardComponent_Conditional_16_Template, 2, 4, "div", 13);
|
|
2348
|
+
i0.ɵɵelementStart(17, "mj-view-config-panel", 14);
|
|
2349
|
+
i0.ɵɵlistener("close", function DataExplorerDashboardComponent_Template_mj_view_config_panel_close_17_listener() { return ctx.onCloseViewConfigPanel(); })("save", function DataExplorerDashboardComponent_Template_mj_view_config_panel_save_17_listener($event) { return ctx.onSaveView($event); })("delete", function DataExplorerDashboardComponent_Template_mj_view_config_panel_delete_17_listener() { return ctx.onDeleteView(); })("openFilterDialogRequest", function DataExplorerDashboardComponent_Template_mj_view_config_panel_openFilterDialogRequest_17_listener($event) { return ctx.onOpenFilterDialogRequest($event); });
|
|
2350
|
+
i0.ɵɵelementEnd();
|
|
2351
|
+
i0.ɵɵelementStart(18, "mj-filter-dialog", 15);
|
|
2352
|
+
i0.ɵɵlistener("close", function DataExplorerDashboardComponent_Template_mj_filter_dialog_close_18_listener() { return ctx.onCloseFilterDialog(); })("apply", function DataExplorerDashboardComponent_Template_mj_filter_dialog_apply_18_listener($event) { return ctx.onFilterApplied($event); });
|
|
2050
2353
|
i0.ɵɵelementEnd()();
|
|
2051
2354
|
} if (rf & 2) {
|
|
2052
2355
|
i0.ɵɵadvance();
|
|
@@ -2068,8 +2371,10 @@ let DataExplorerDashboardComponent = class DataExplorerDashboardComponent extend
|
|
|
2068
2371
|
i0.ɵɵadvance(2);
|
|
2069
2372
|
i0.ɵɵconditional(ctx.state.detailPanelOpen && ctx.selectedRecord ? 16 : -1);
|
|
2070
2373
|
i0.ɵɵadvance();
|
|
2071
|
-
i0.ɵɵproperty("entity", ctx.selectedEntity)("viewEntity", ctx.selectedViewEntity)("isOpen", ctx.state.viewConfigPanelOpen)("currentGridState", ctx.currentGridState);
|
|
2072
|
-
} }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i5.EntityViewerComponent, i5.EntityRecordDetailPanelComponent, i3.LoadingComponent, i6.NavigationPanelComponent, i7.ViewSelectorComponent, i8.ViewConfigPanelComponent, i9.DecimalPipe], styles: [".data-explorer-container[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n width: 100%;\n background: #f5f7fa;\n overflow: hidden;\n}\n\n.navigation-panel[_ngcontent-%COMP%] {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-right: 1px solid #e0e0e0;\n transition: width 0.2s ease-in-out;\n overflow: hidden;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);\n}\n.navigation-panel.collapsed[_ngcontent-%COMP%] {\n width: 48px;\n}\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n overflow: hidden;\n background: #f5f7fa;\n}\n\n\n\n.breadcrumb-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 24px;\n background: white;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\n font-size: 13px;\n min-height: 40px;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #666;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s ease;\n max-width: 200px;\n}\n\n.breadcrumb-item.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.breadcrumb-item.clickable[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n color: #1976d2;\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%] {\n color: #1a1a1a;\n font-weight: 500;\n cursor: default;\n}\n\n.breadcrumb-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.breadcrumb-label[_ngcontent-%COMP%] {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.breadcrumb-separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #ccc;\n flex-shrink: 0;\n}\n\n.content-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n gap: 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n flex-wrap: wrap;\n}\n\n\n\n.header-left[_ngcontent-%COMP%] mj-view-selector {\n margin-left: 8px;\n}\n\n.entity-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #1a1a1a;\n}\n\n.record-count[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #666;\n font-weight: 500;\n}\n\n.header-center[_ngcontent-%COMP%] {\n flex: 1;\n max-width: 600px;\n}\n\n.smart-filter-container[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n}\n\n.smart-filter-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 40px 10px 16px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n font-size: 14px;\n background: #fafafa;\n transition: all 0.15s ease;\n}\n.smart-filter-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n background: white;\n box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);\n}\n.smart-filter-input[_ngcontent-%COMP%]::placeholder {\n color: #999;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: #e0e0e0;\n color: #424242;\n}\n\n.header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 8px;\n padding: 3px;\n}\n\n.toggle-btn[_ngcontent-%COMP%] {\n width: 36px;\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: #666;\n transition: all 0.15s ease;\n}\n.toggle-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n.toggle-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.content-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n display: flex;\n flex-direction: column;\n}\n\n.loading-container[_ngcontent-%COMP%], \n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n background: white;\n border-radius: 8px;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #1976d2;\n}\n\n.loading-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: #666;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: #757575;\n background: white;\n border-radius: 8px;\n padding: 40px;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 64px;\n color: #e0e0e0;\n margin-bottom: 24px;\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n color: #666;\n}\n\n\n\n.entity-home-view[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 4px;\n}\n\n.entity-card-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 16px;\n padding: 0;\n}\n\n.entity-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 1px solid #e8e8e8;\n}\n\n.entity-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);\n border-color: #1976d2;\n}\n\n.entity-card[_ngcontent-%COMP%]:active {\n transform: translateY(0);\n}\n\n.entity-card-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 10px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-card[_ngcontent-%COMP%]:hover .entity-card-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #1976d2, #1565c0);\n}\n\n.entity-card[_ngcontent-%COMP%]:hover .entity-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: white;\n}\n\n.entity-card-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.entity-card-title[_ngcontent-%COMP%] {\n margin: 0 0 6px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-card-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.detail-panel[_ngcontent-%COMP%] {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-left: 1px solid #e0e0e0;\n box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n[_nghost-%COMP%] mj-explorer-grid-view, \n[_nghost-%COMP%] mj-explorer-cards-view {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n\n\n\n\n\n\n\n.content-header.home-header[_ngcontent-%COMP%] {\n border-bottom: none;\n background: transparent;\n box-shadow: none;\n padding: 24px 24px 16px;\n}\n\n.content-body.home-content[_ngcontent-%COMP%] {\n padding-top: 0;\n}\n\n\n\n.filter-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: #999;\n font-size: 14px;\n pointer-events: none;\n}\n\n.smart-filter-container[_ngcontent-%COMP%] .smart-filter-input[_ngcontent-%COMP%] {\n padding-left: 40px;\n}\n\n\n\n\n\n\n.home-section[_ngcontent-%COMP%] {\n margin-bottom: 28px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #1976d2;\n width: 20px;\n text-align: center;\n}\n\n.section-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n font-weight: 500;\n margin-left: 8px;\n}\n\n\n\n\n\n\n.home-two-column-layout[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 24px;\n margin-bottom: 28px;\n}\n\n.home-column[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n\n\n.section-header-with-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n\n\n.inline-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.inline-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%] {\n width: auto;\n height: 26px;\n padding: 0 10px;\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: #666;\n font-size: 11px;\n font-weight: 500;\n transition: all 0.15s ease;\n}\n\n.inline-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.inline-toggle[_ngcontent-%COMP%] .toggle-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n\n\n\n.entity-card-row[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding: 0;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n width: auto;\n min-width: 180px;\n max-width: 280px;\n padding: 12px 16px;\n gap: 12px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n}\n\n\n\n\n\n\n.favorite-btn[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #ccc;\n transition: all 0.15s ease;\n margin-left: auto;\n}\n\n.favorite-btn[_ngcontent-%COMP%]:hover {\n background: rgba(255, 193, 7, 0.1);\n color: #ffc107;\n transform: scale(1.1);\n}\n\n.favorite-btn.favorited[_ngcontent-%COMP%] {\n color: #ffc107;\n}\n\n.favorite-btn.favorited[_ngcontent-%COMP%]:hover {\n background: rgba(255, 193, 7, 0.15);\n color: #ffb300;\n}\n\n.entity-card[_ngcontent-%COMP%] .favorite-btn[_ngcontent-%COMP%] {\n opacity: 0;\n transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;\n}\n\n.entity-card[_ngcontent-%COMP%]:hover .favorite-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.entity-card[_ngcontent-%COMP%] .favorite-btn.favorited[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n\n\n\n.recent-records-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.recent-record-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.recent-record-item[_ngcontent-%COMP%]:hover {\n background: #f5f7fa;\n}\n\n.recent-record-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e8f5e9, #c8e6c9);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.recent-record-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #4caf50;\n}\n\n.recent-record-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.recent-record-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recent-record-entity[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n}\n\n.recent-record-time[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #aaa;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n.entity-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.entity-list-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.entity-list-item[_ngcontent-%COMP%]:hover {\n background: #f5f7fa;\n}\n\n.entity-list-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-list-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #1976d2;\n}\n\n.entity-list-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.entity-list-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-list-item[_ngcontent-%COMP%] .favorite-btn[_ngcontent-%COMP%] {\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.entity-list-item[_ngcontent-%COMP%]:hover .favorite-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.entity-list-item[_ngcontent-%COMP%] .favorite-btn.favorited[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n\n\n\n.entity-filter-strip[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-left: auto;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 3px;\n}\n\n.entity-filter-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 26px;\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: #666;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.entity-filter-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.entity-filter-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%] {\n width: auto;\n padding: 0 12px;\n gap: 6px;\n}\n\n.toggle-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n}\n\n\n\n\n\n\n.empty-state.small[_ngcontent-%COMP%] {\n height: auto;\n padding: 32px;\n background: #fafafa;\n}\n\n.empty-state.small[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 40px;\n margin-bottom: 16px;\n}\n\n.empty-state.small[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.empty-state.small[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n\n\n\n@media (max-width: 1200px) {\n .entity-card-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n }\n}\n\n@media (max-width: 900px) {\n .content-header[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .header-center[_ngcontent-%COMP%] {\n order: 3;\n flex-basis: 100%;\n max-width: 100%;\n }\n\n .entity-card.compact[_ngcontent-%COMP%] {\n min-width: 160px;\n }\n\n \n\n .home-two-column-layout[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 20px;\n }\n}\n\n@media (max-width: 600px) {\n .data-explorer-container[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .navigation-panel[_ngcontent-%COMP%] {\n display: none;\n }\n\n .content-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .content-body[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .entity-card-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 12px;\n }\n\n .entity-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .entity-card.compact[_ngcontent-%COMP%] {\n min-width: 100%;\n max-width: 100%;\n }\n\n .entity-card-row[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .view-mode-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n\n .section-title[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .home-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n }\n}"], data: { animation: [
|
|
2374
|
+
i0.ɵɵproperty("entity", ctx.selectedEntity)("viewEntity", ctx.selectedViewEntity)("isOpen", ctx.state.viewConfigPanelOpen)("currentGridState", ctx.currentGridState)("externalFilterState", ctx.filterDialogState);
|
|
2375
|
+
i0.ɵɵadvance();
|
|
2376
|
+
i0.ɵɵproperty("isOpen", ctx.isFilterDialogOpen)("fields", ctx.filterDialogFields)("filter", ctx.filterDialogState)("disabled", ctx.filterDialogDisabled);
|
|
2377
|
+
} }, dependencies: [i5.DefaultValueAccessor, i5.NgControlStatus, i5.NgModel, i6.EntityViewerComponent, i6.EntityRecordDetailPanelComponent, i3.LoadingComponent, i7.NavigationPanelComponent, i8.ViewSelectorComponent, i9.ViewConfigPanelComponent, i10.FilterDialogComponent, i11.DecimalPipe], styles: [".data-explorer-container[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n width: 100%;\n background: #f5f7fa;\n overflow: hidden;\n}\n\n.navigation-panel[_ngcontent-%COMP%] {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-right: 1px solid #e0e0e0;\n transition: width 0.2s ease-in-out;\n overflow: hidden;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);\n}\n.navigation-panel.collapsed[_ngcontent-%COMP%] {\n width: 48px;\n}\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n overflow: hidden;\n background: #f5f7fa;\n}\n\n\n\n.breadcrumb-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 24px;\n background: white;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\n font-size: 13px;\n min-height: 40px;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #666;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s ease;\n max-width: 200px;\n}\n\n.breadcrumb-item.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.breadcrumb-item.clickable[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n color: #1976d2;\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%] {\n color: #1a1a1a;\n font-weight: 500;\n cursor: default;\n}\n\n.breadcrumb-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.breadcrumb-label[_ngcontent-%COMP%] {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.breadcrumb-separator[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #ccc;\n flex-shrink: 0;\n}\n\n.content-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n gap: 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n flex-wrap: wrap;\n}\n\n\n\n.header-left[_ngcontent-%COMP%] mj-view-selector {\n margin-left: 8px;\n}\n\n.entity-icon[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #1a1a1a;\n}\n\n.record-count[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #666;\n font-weight: 500;\n}\n\n.header-center[_ngcontent-%COMP%] {\n flex: 1;\n max-width: 600px;\n}\n\n.smart-filter-container[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n}\n\n.smart-filter-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 40px 10px 16px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n font-size: 14px;\n background: #fafafa;\n transition: all 0.15s ease;\n}\n.smart-filter-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n background: white;\n box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);\n}\n.smart-filter-input[_ngcontent-%COMP%]::placeholder {\n color: #999;\n}\n\n.clear-filter-btn[_ngcontent-%COMP%] {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n.clear-filter-btn[_ngcontent-%COMP%]:hover {\n background: #e0e0e0;\n color: #424242;\n}\n\n.header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 8px;\n padding: 3px;\n}\n\n.toggle-btn[_ngcontent-%COMP%] {\n width: 36px;\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: #666;\n transition: all 0.15s ease;\n}\n.toggle-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n.toggle-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n.date-field-selector-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n position: relative;\n}\n\n.date-field-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.date-field-selector-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.date-field-selector-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--background-alt, #f5f5f5);\n border: 1px solid var(--border-color, #e0e0e0);\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n color: var(--text-primary, #333);\n transition: all 0.15s ease;\n min-width: 120px;\n max-width: 200px;\n}\n\n.date-field-selector-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--background-hover, #e8e8e8);\n border-color: var(--border-color-hover, #ccc);\n}\n\n.date-field-selector-button[_ngcontent-%COMP%]:disabled {\n cursor: default;\n opacity: 0.8;\n}\n\n.date-field-selector-button.open[_ngcontent-%COMP%] {\n background: var(--background-active, #e0e0e0);\n border-color: var(--primary-color, #007bff);\n}\n\n.date-field-icon[_ngcontent-%COMP%] {\n color: var(--text-secondary, #666);\n font-size: 12px;\n}\n\n.date-field-name[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.date-field-arrow[_ngcontent-%COMP%] {\n color: var(--text-secondary, #666);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.date-field-arrow.rotated[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n.date-field-dropdown-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n min-width: 180px;\n max-width: 280px;\n max-height: 300px;\n overflow-y: auto;\n background: var(--background-panel, #fff);\n border: 1px solid var(--border-color, #e0e0e0);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n z-index: 1000;\n}\n\n.date-field-dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n transition: background 0.1s ease;\n font-size: 13px;\n}\n\n.date-field-dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--background-hover, #f5f5f5);\n}\n\n.date-field-dropdown-item.selected[_ngcontent-%COMP%] {\n background: var(--primary-light, #e6f0ff);\n}\n\n.date-field-dropdown-item.selected[_ngcontent-%COMP%]:hover {\n background: var(--primary-light-hover, #d6e4f9);\n}\n\n.date-field-dropdown-item[_ngcontent-%COMP%] .item-icon[_ngcontent-%COMP%] {\n color: var(--text-secondary, #666);\n font-size: 13px;\n width: 16px;\n text-align: center;\n}\n\n.date-field-dropdown-item[_ngcontent-%COMP%] .item-name[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.date-field-dropdown-item[_ngcontent-%COMP%] .selected-check[_ngcontent-%COMP%] {\n color: var(--primary-color, #007bff);\n font-size: 12px;\n}\n\n\n\n.timeline-orientation-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 8px;\n padding: 3px;\n}\n\n.content-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n display: flex;\n flex-direction: column;\n}\n\n.loading-container[_ngcontent-%COMP%], \n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n background: white;\n border-radius: 8px;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #1976d2;\n}\n\n.loading-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: #666;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: #757575;\n background: white;\n border-radius: 8px;\n padding: 40px;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 64px;\n color: #e0e0e0;\n margin-bottom: 24px;\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n color: #666;\n}\n\n\n\n.entity-home-view[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 4px;\n}\n\n.entity-card-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 16px;\n padding: 0;\n}\n\n.entity-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 1px solid #e8e8e8;\n}\n\n.entity-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);\n border-color: #1976d2;\n}\n\n.entity-card[_ngcontent-%COMP%]:active {\n transform: translateY(0);\n}\n\n.entity-card-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 10px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-card[_ngcontent-%COMP%]:hover .entity-card-icon[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #1976d2, #1565c0);\n}\n\n.entity-card[_ngcontent-%COMP%]:hover .entity-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: white;\n}\n\n.entity-card-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.entity-card-title[_ngcontent-%COMP%] {\n margin: 0 0 6px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-card-description[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.detail-panel[_ngcontent-%COMP%] {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-left: 1px solid #e0e0e0;\n box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n[_nghost-%COMP%] mj-explorer-grid-view, \n[_nghost-%COMP%] mj-explorer-cards-view {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n\n\n\n\n\n\n\n.content-header.home-header[_ngcontent-%COMP%] {\n border-bottom: none;\n background: transparent;\n box-shadow: none;\n padding: 24px 24px 16px;\n}\n\n.content-body.home-content[_ngcontent-%COMP%] {\n padding-top: 0;\n}\n\n\n\n.filter-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: #999;\n font-size: 14px;\n pointer-events: none;\n}\n\n.smart-filter-container[_ngcontent-%COMP%] .smart-filter-input[_ngcontent-%COMP%] {\n padding-left: 40px;\n}\n\n\n\n\n\n\n.home-section[_ngcontent-%COMP%] {\n margin-bottom: 28px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-icon[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #1976d2;\n width: 20px;\n text-align: center;\n}\n\n.section-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n font-weight: 500;\n margin-left: 8px;\n}\n\n\n\n\n\n\n.home-two-column-layout[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 24px;\n margin-bottom: 28px;\n}\n\n\n\n.home-two-column-layout.single-column[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n}\n\n.home-column[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n\n\n.section-header-with-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n\n\n.inline-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.inline-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%] {\n width: auto;\n height: 26px;\n padding: 0 10px;\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: #666;\n font-size: 11px;\n font-weight: 500;\n transition: all 0.15s ease;\n}\n\n.inline-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.inline-toggle[_ngcontent-%COMP%] .toggle-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n\n\n\n.entity-card-row[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding: 0;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n width: auto;\n min-width: 180px;\n max-width: 280px;\n padding: 12px 16px;\n gap: 12px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n.entity-card.compact[_ngcontent-%COMP%] .entity-card-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n}\n\n\n\n\n\n\n.favorite-btn[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #ccc;\n transition: all 0.15s ease;\n margin-left: auto;\n}\n\n.favorite-btn[_ngcontent-%COMP%]:hover {\n background: rgba(255, 193, 7, 0.1);\n color: #ffc107;\n transform: scale(1.1);\n}\n\n.favorite-btn.favorited[_ngcontent-%COMP%] {\n color: #ffc107;\n}\n\n.favorite-btn.favorited[_ngcontent-%COMP%]:hover {\n background: rgba(255, 193, 7, 0.15);\n color: #ffb300;\n}\n\n.entity-card[_ngcontent-%COMP%] .favorite-btn[_ngcontent-%COMP%] {\n opacity: 0;\n transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;\n}\n\n.entity-card[_ngcontent-%COMP%]:hover .favorite-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.entity-card[_ngcontent-%COMP%] .favorite-btn.favorited[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n\n\n\n.recent-records-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.recent-record-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.recent-record-item[_ngcontent-%COMP%]:hover {\n background: #f5f7fa;\n}\n\n.recent-record-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e8f5e9, #c8e6c9);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.recent-record-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #4caf50;\n}\n\n.recent-record-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.recent-record-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recent-record-entity[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n}\n\n.recent-record-time[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #aaa;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n.entity-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.entity-list-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.entity-list-item[_ngcontent-%COMP%]:hover {\n background: #f5f7fa;\n}\n\n.entity-list-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-list-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #1976d2;\n}\n\n.entity-list-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.entity-list-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-list-item[_ngcontent-%COMP%] .favorite-btn[_ngcontent-%COMP%] {\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.entity-list-item[_ngcontent-%COMP%]:hover .favorite-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.entity-list-item[_ngcontent-%COMP%] .favorite-btn.favorited[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n\n\n\n\n\n.entity-filter-strip[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n margin-left: auto;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 3px;\n}\n\n.entity-filter-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 26px;\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: #666;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.entity-filter-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.entity-filter-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] .toggle-btn[_ngcontent-%COMP%] {\n width: auto;\n padding: 0 12px;\n gap: 6px;\n}\n\n.toggle-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n}\n\n\n\n\n\n\n.empty-state.small[_ngcontent-%COMP%] {\n height: auto;\n padding: 32px;\n background: #fafafa;\n}\n\n.empty-state.small[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 40px;\n margin-bottom: 16px;\n}\n\n.empty-state.small[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 16px;\n}\n\n.empty-state.small[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n\n\n\n@media (max-width: 1200px) {\n .entity-card-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n }\n}\n\n@media (max-width: 900px) {\n .content-header[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .header-center[_ngcontent-%COMP%] {\n order: 3;\n flex-basis: 100%;\n max-width: 100%;\n }\n\n .entity-card.compact[_ngcontent-%COMP%] {\n min-width: 160px;\n }\n\n \n\n .home-two-column-layout[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 20px;\n }\n}\n\n@media (max-width: 600px) {\n .data-explorer-container[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .navigation-panel[_ngcontent-%COMP%] {\n display: none;\n }\n\n .content-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .content-body[_ngcontent-%COMP%] {\n padding: 12px 16px;\n }\n\n .entity-card-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 12px;\n }\n\n .entity-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .entity-card.compact[_ngcontent-%COMP%] {\n min-width: 100%;\n max-width: 100%;\n }\n\n .entity-card-row[_ngcontent-%COMP%] {\n flex-direction: column;\n }\n\n .view-mode-toggle[_ngcontent-%COMP%] {\n display: none;\n }\n\n .section-title[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .home-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n }\n}"], data: { animation: [
|
|
2073
2378
|
trigger('slideInLeft', [
|
|
2074
2379
|
transition(':enter', [
|
|
2075
2380
|
style({ transform: 'translateX(-100%)', opacity: 0 }),
|
|
@@ -2097,8 +2402,8 @@ export { DataExplorerDashboardComponent };
|
|
|
2097
2402
|
animate('200ms ease-in', style({ transform: 'translateX(-100%)', opacity: 0 }))
|
|
2098
2403
|
])
|
|
2099
2404
|
])
|
|
2100
|
-
], template: "<div class=\"data-explorer-container\">\n <!-- Navigation Panel (Left) - Hidden at home level, animated -->\n @if (!isAtHomeLevel) {\n <div\n class=\"navigation-panel\"\n [class.collapsed]=\"state.navigationPanelCollapsed\"\n [style.width.px]=\"state.navigationPanelCollapsed ? 48 : state.navigationPanelWidth\"\n [@slideInLeft]>\n\n <mj-explorer-navigation-panel\n [entities]=\"entities\"\n [selectedEntityName]=\"state.selectedEntityName\"\n [favorites]=\"state.favorites\"\n [recentItems]=\"state.recentItems\"\n [collapsed]=\"state.navigationPanelCollapsed\"\n [allowedEntityNames]=\"allowedEntityNames\"\n [favoritesSectionExpanded]=\"state.favoritesSectionExpanded\"\n [recentSectionExpanded]=\"state.recentSectionExpanded\"\n [entitiesSectionExpanded]=\"state.entitiesSectionExpanded\"\n [viewsSectionExpanded]=\"state.viewsSectionExpanded\"\n (entitySelected)=\"onEntitySelected($event)\"\n (toggleCollapse)=\"toggleNavigationPanel()\"\n (sectionToggled)=\"stateService.toggleSection($event)\"\n (openRecord)=\"onOpenRecordFromNav($event)\"\n (selectRecord)=\"onSelectRecordFromNav($event)\"\n (expandAndFocus)=\"onExpandAndFocus($event)\">\n </mj-explorer-navigation-panel>\n </div>\n }\n\n <!-- Main Content Area -->\n <div class=\"content-area\">\n <!-- Breadcrumb Bar - Hidden at home level -->\n @if (!isAtHomeLevel && breadcrumbs.length > 0) {\n <div class=\"breadcrumb-bar\">\n @for (crumb of breadcrumbs; track crumb.label; let i = $index; let last = $last) {\n <span\n class=\"breadcrumb-item\"\n [class.clickable]=\"!last\"\n [class.current]=\"last\"\n (click)=\"onBreadcrumbClick(crumb, i)\"\n [title]=\"crumb.label\">\n @if (crumb.icon) {\n <i [class]=\"crumb.icon\" class=\"breadcrumb-icon\"></i>\n }\n <span class=\"breadcrumb-label\">{{ crumb.label }}</span>\n </span>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n }\n\n <!-- Header -->\n <div class=\"content-header\" [class.home-header]=\"isAtHomeLevel\">\n <div class=\"header-left\">\n @if (selectedEntity) {\n <i [class]=\"getEntityIcon(selectedEntity)\" class=\"entity-icon\"></i>\n <h2 class=\"entity-title\">{{ selectedEntity.Name }}</h2>\n @if (debouncedFilterText && filteredRecordCount !== totalRecordCount) {\n <span class=\"record-count\">{{ filteredRecordCount | number }} of {{ totalRecordCount | number }} records</span>\n } @else {\n <span class=\"record-count\">{{ totalRecordCount | number }} records</span>\n }\n\n <!-- View Selector -->\n <mj-view-selector\n [entity]=\"selectedEntity\"\n [selectedViewId]=\"state.selectedViewId\"\n [viewModified]=\"state.viewModified\"\n (viewSelected)=\"onViewSelected($event)\"\n (saveViewRequested)=\"onSaveViewRequested($event)\"\n (manageViewsRequested)=\"onManageViewsRequested()\"\n (openInTabRequested)=\"onOpenInTabRequested($event)\"\n (configureViewRequested)=\"onConfigureViewRequested()\">\n </mj-view-selector>\n } @else {\n @if (displayIcon) {\n <i [class]=\"displayIcon\" class=\"entity-icon\"></i>\n }\n <h2 class=\"entity-title\">{{ displayTitle }}</h2>\n <span class=\"record-count\">{{ entities.length }} entities available</span>\n }\n </div>\n\n <div class=\"header-center\">\n @if (selectedEntity) {\n <div class=\"smart-filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"smart-filter-input\"\n placeholder=\"Filter records... (press / to focus)\"\n [ngModel]=\"state.smartFilterPrompt\"\n (ngModelChange)=\"onSmartFilterChanged($event)\"\n />\n @if (state.smartFilterPrompt) {\n <button class=\"clear-filter-btn\" (click)=\"onSmartFilterChanged('')\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n } @else {\n <!-- Entity filter for home screen -->\n <div class=\"smart-filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"smart-filter-input\"\n placeholder=\"Filter entities... (press / to focus)\"\n [(ngModel)]=\"entityFilterText\"\n />\n @if (entityFilterText) {\n <button class=\"clear-filter-btn\" (click)=\"entityFilterText = ''\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n </div>\n\n <div class=\"header-right\">\n @if (selectedEntity) {\n <!-- View Mode Toggle -->\n <div class=\"view-mode-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.viewMode === 'grid'\"\n (click)=\"onViewModeChanged('grid')\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.viewMode === 'cards'\"\n (click)=\"onViewModeChanged('cards')\"\n title=\"Cards View\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n </div>\n }\n <!-- Common/All toggle moved to inline with All Entities section header -->\n </div>\n </div>\n\n <!-- Content Body - Using mj-entity-viewer composite -->\n <div class=\"content-body\" [class.home-content]=\"isAtHomeLevel\">\n @if (!selectedEntity) {\n <!-- Entity Home View - Two-Column Layout -->\n <div class=\"entity-home-view\">\n @if (isLoadingEntities) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading entities...\" size=\"medium\"></mj-loading>\n </div>\n } @else {\n <!-- Two-Column Layout: Records (left) | Entities (right) -->\n @if (hasTopSectionContent) {\n <div class=\"home-two-column-layout\">\n <!-- Left Column: Recent & Favorite Records (most actionable) -->\n <div class=\"home-column\">\n <!-- Recent Records Section -->\n @if (recentRecords.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-history section-icon\"></i>\n <h3 class=\"section-title\">Recent Records</h3>\n <!-- Entity filter strip - only show with 2+ entities -->\n @if (showRecentRecordsEntityFilter) {\n <div class=\"entity-filter-strip\">\n <button\n class=\"entity-filter-btn\"\n [class.active]=\"recentRecordsEntityFilter === null\"\n (click)=\"setRecentRecordsEntityFilter(null)\"\n title=\"Show all entities\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </button>\n @for (entity of uniqueRecentRecordEntities; track entity.entityId) {\n <button\n class=\"entity-filter-btn\"\n [class.active]=\"recentRecordsEntityFilter === entity.entityId\"\n (click)=\"setRecentRecordsEntityFilter(entity.entityId)\"\n [title]=\"entity.entityName\">\n <i [class]=\"entity.icon\"></i>\n </button>\n }\n </div>\n }\n </div>\n <div class=\"recent-records-list\">\n @for (record of filteredRecentRecords; track record.entityId + '|' + record.recordId) {\n <div\n class=\"recent-record-item\"\n (click)=\"onRecentRecordClick(record)\"\n [title]=\"record.entityName + ' - ' + record.recordId\">\n <div class=\"recent-record-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"recent-record-content\">\n <span class=\"recent-record-name\">{{ record.recordName || record.recordId }}</span>\n <span class=\"recent-record-entity\">{{ record.entityName }}</span>\n </div>\n <span class=\"recent-record-time\">{{ formatRelativeTime(record.latestAt) }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Favorite Records Section -->\n @if (favoriteRecords.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <h3 class=\"section-title\">Favorite Records</h3>\n </div>\n <div class=\"recent-records-list\">\n @for (record of favoriteRecords; track record.userFavoriteId) {\n <div\n class=\"recent-record-item\"\n (click)=\"onFavoriteRecordClick(record)\"\n [title]=\"record.entityName + ' - ' + record.recordId\">\n <div class=\"recent-record-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"recent-record-content\">\n <span class=\"recent-record-name\">{{ record.recordName || record.recordId }}</span>\n <span class=\"recent-record-entity\">{{ record.entityName }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Right Column: Recent & Favorite Entities -->\n <div class=\"home-column\">\n <!-- Recent Entities Section (list format) -->\n @if (recentEntities.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-clock section-icon\"></i>\n <h3 class=\"section-title\">Recent Entities</h3>\n </div>\n <div class=\"entity-list\">\n @for (entity of recentEntities; track entity.ID) {\n <div\n class=\"entity-list-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.Name\">\n <div class=\"entity-list-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-list-content\">\n <span class=\"entity-list-name\">{{ entity.Name }}</span>\n </div>\n <button\n class=\"favorite-btn\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Favorite Entities Section (list format) -->\n @if (favoriteEntities.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <h3 class=\"section-title\">Favorite Entities</h3>\n </div>\n <div class=\"entity-list\">\n @for (entity of favoriteEntities; track entity.ID) {\n <div\n class=\"entity-list-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.Name\">\n <div class=\"entity-list-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-list-content\">\n <span class=\"entity-list-name\">{{ entity.Name }}</span>\n </div>\n <button\n class=\"favorite-btn favorited\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n title=\"Remove from favorites\">\n <i class=\"fa-solid fa-star\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- All/Common Entities Section - Full Width -->\n <div class=\"home-section\">\n <div class=\"section-header-with-toggle\">\n <div class=\"section-header-left\">\n <i class=\"fa-solid fa-database section-icon\"></i>\n <h3 class=\"section-title\">\n @if (state.showAllEntities || !showCommonAllToggle) {\n All Entities\n } @else {\n Common Entities\n }\n </h3>\n @if (entityFilterText && filteredEntities.length !== entities.length) {\n <span class=\"section-count\">{{ filteredEntities.length }} matching</span>\n }\n </div>\n @if (showCommonAllToggle) {\n <div class=\"inline-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"!state.showAllEntities\"\n (click)=\"toggleShowAllEntities()\"\n title=\"Show common entities ({{ commonEntitiesCount }})\">\n Common\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.showAllEntities\"\n (click)=\"toggleShowAllEntities()\"\n title=\"Show all entities ({{ allEntitiesCount }})\">\n All\n </button>\n </div>\n }\n </div>\n <div class=\"entity-card-grid\">\n @for (entity of filteredEntities; track entity.ID) {\n <div\n class=\"entity-card\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.Name\">\n <div class=\"entity-card-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-card-content\">\n <h4 class=\"entity-card-title\">{{ entity.Name }}</h4>\n @if (entity.Description) {\n <p class=\"entity-card-description\">{{ entity.Description }}</p>\n }\n </div>\n <button\n class=\"favorite-btn\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n @if (filteredEntities.length === 0 && entities.length > 0) {\n <div class=\"empty-state small\">\n <i class=\"fa-solid fa-search empty-icon\"></i>\n <h3>No Matching Entities</h3>\n <p>No entities match \"{{ entityFilterText }}\"</p>\n </div>\n }\n @if (entities.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-database empty-icon\"></i>\n <h3>No Entities Available</h3>\n <p>There are no entities configured for this application.</p>\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <mj-entity-viewer\n [entity]=\"selectedEntity\"\n [viewEntity]=\"selectedViewEntity\"\n [viewMode]=\"state.viewMode\"\n [filterText]=\"debouncedFilterText\"\n [selectedRecordId]=\"state.selectedRecordId\"\n [config]=\"viewerConfig\"\n [gridState]=\"currentGridState\"\n (viewModeChange)=\"onViewModeChanged($event)\"\n (filterTextChange)=\"onFilterTextChanged($event)\"\n (recordSelected)=\"onViewerRecordSelected($event)\"\n (recordOpened)=\"onViewerRecordOpened($event)\"\n (dataLoaded)=\"onDataLoaded($event)\"\n (filteredCountChanged)=\"onFilteredCountChanged($event)\"\n (gridStateChanged)=\"onGridStateChanged($event)\">\n </mj-entity-viewer>\n }\n </div>\n </div>\n\n <!-- Detail Panel (Right - Slide In) -->\n @if (state.detailPanelOpen && selectedRecord) {\n <div class=\"detail-panel\" [style.width.px]=\"state.detailPanelWidth\">\n <mj-entity-record-detail-panel\n [entity]=\"detailPanelEntity\"\n [record]=\"selectedRecord\"\n (close)=\"onDetailPanelClosed()\"\n (openRecord)=\"onOpenRecord($event)\"\n (navigateToRelated)=\"onNavigateToRelated($event)\"\n (openRelatedRecord)=\"onOpenRelatedRecord($event)\"\n (openForeignKeyRecord)=\"onOpenForeignKeyRecord($event)\">\n </mj-entity-record-detail-panel>\n </div>\n }\n\n <!-- View Configuration Panel -->\n <mj-view-config-panel\n [entity]=\"selectedEntity\"\n [viewEntity]=\"selectedViewEntity\"\n [isOpen]=\"state.viewConfigPanelOpen\"\n [currentGridState]=\"currentGridState\"\n (close)=\"onCloseViewConfigPanel()\"\n (save)=\"onSaveView($event)\"\n (delete)=\"onDeleteView()\">\n </mj-view-config-panel>\n</div>\n", styles: [".data-explorer-container {\n display: flex;\n height: 100%;\n width: 100%;\n background: #f5f7fa;\n overflow: hidden;\n}\n\n.navigation-panel {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-right: 1px solid #e0e0e0;\n transition: width 0.2s ease-in-out;\n overflow: hidden;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);\n}\n.navigation-panel.collapsed {\n width: 48px;\n}\n\n.content-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n overflow: hidden;\n background: #f5f7fa;\n}\n\n/* Breadcrumb Bar */\n.breadcrumb-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 24px;\n background: white;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\n font-size: 13px;\n min-height: 40px;\n}\n\n.breadcrumb-item {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #666;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s ease;\n max-width: 200px;\n}\n\n.breadcrumb-item.clickable {\n cursor: pointer;\n}\n\n.breadcrumb-item.clickable:hover {\n background: #f0f0f0;\n color: #1976d2;\n}\n\n.breadcrumb-item.current {\n color: #1a1a1a;\n font-weight: 500;\n cursor: default;\n}\n\n.breadcrumb-icon {\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.breadcrumb-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.breadcrumb-separator {\n font-size: 10px;\n color: #ccc;\n flex-shrink: 0;\n}\n\n.content-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n gap: 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n flex-wrap: wrap;\n}\n\n/* View Selector within header */\n.header-left ::ng-deep mj-view-selector {\n margin-left: 8px;\n}\n\n.entity-icon {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-title {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #1a1a1a;\n}\n\n.record-count {\n font-size: 13px;\n color: #666;\n font-weight: 500;\n}\n\n.header-center {\n flex: 1;\n max-width: 600px;\n}\n\n.smart-filter-container {\n position: relative;\n width: 100%;\n}\n\n.smart-filter-input {\n width: 100%;\n padding: 10px 40px 10px 16px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n font-size: 14px;\n background: #fafafa;\n transition: all 0.15s ease;\n}\n.smart-filter-input:focus {\n outline: none;\n border-color: #1976d2;\n background: white;\n box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);\n}\n.smart-filter-input::placeholder {\n color: #999;\n}\n\n.clear-filter-btn {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n.clear-filter-btn:hover {\n background: #e0e0e0;\n color: #424242;\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.view-mode-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 8px;\n padding: 3px;\n}\n\n.toggle-btn {\n width: 36px;\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: #666;\n transition: all 0.15s ease;\n}\n.toggle-btn:hover {\n color: #333;\n}\n.toggle-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.content-body {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n display: flex;\n flex-direction: column;\n}\n\n.loading-container,\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n background: white;\n border-radius: 8px;\n}\n\n.loading-spinner {\n font-size: 32px;\n color: #1976d2;\n}\n\n.loading-message {\n margin: 0;\n font-size: 14px;\n color: #666;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: #757575;\n background: white;\n border-radius: 8px;\n padding: 40px;\n}\n\n.empty-icon {\n font-size: 64px;\n color: #e0e0e0;\n margin-bottom: 24px;\n}\n\n.empty-state h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n color: #666;\n}\n\n/* Entity Home View - Card Grid */\n.entity-home-view {\n flex: 1;\n overflow: auto;\n padding: 4px;\n}\n\n.entity-card-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 16px;\n padding: 0;\n}\n\n.entity-card {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 1px solid #e8e8e8;\n}\n\n.entity-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);\n border-color: #1976d2;\n}\n\n.entity-card:active {\n transform: translateY(0);\n}\n\n.entity-card-icon {\n width: 48px;\n height: 48px;\n border-radius: 10px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-card-icon i {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-card:hover .entity-card-icon {\n background: linear-gradient(135deg, #1976d2, #1565c0);\n}\n\n.entity-card:hover .entity-card-icon i {\n color: white;\n}\n\n.entity-card-content {\n flex: 1;\n min-width: 0;\n}\n\n.entity-card-title {\n margin: 0 0 6px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-card-description {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.detail-panel {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-left: 1px solid #e0e0e0;\n box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n animation: slideIn 0.2s ease-out;\n}\n\n@keyframes slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n:host ::ng-deep mj-explorer-grid-view,\n:host ::ng-deep mj-explorer-cards-view {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n/* ============================================\n HOME SCREEN STYLES\n ============================================ */\n\n/* Home-level header adjustments */\n.content-header.home-header {\n border-bottom: none;\n background: transparent;\n box-shadow: none;\n padding: 24px 24px 16px;\n}\n\n.content-body.home-content {\n padding-top: 0;\n}\n\n/* Smart filter with search icon */\n.filter-icon {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: #999;\n font-size: 14px;\n pointer-events: none;\n}\n\n.smart-filter-container .smart-filter-input {\n padding-left: 40px;\n}\n\n/* ============================================\n HOME SECTIONS\n ============================================ */\n\n.home-section {\n margin-bottom: 28px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-icon {\n font-size: 14px;\n color: #1976d2;\n width: 20px;\n text-align: center;\n}\n\n.section-title {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-count {\n font-size: 12px;\n color: #888;\n font-weight: 500;\n margin-left: 8px;\n}\n\n/* ============================================\n TWO-COLUMN LAYOUT (Entities left, Records right)\n ============================================ */\n\n.home-two-column-layout {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 24px;\n margin-bottom: 28px;\n}\n\n.home-column {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n/* Section header with inline toggle */\n.section-header-with-toggle {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n/* Inline Common/All toggle (compact) */\n.inline-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.inline-toggle .toggle-btn {\n width: auto;\n height: 26px;\n padding: 0 10px;\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: #666;\n font-size: 11px;\n font-weight: 500;\n transition: all 0.15s ease;\n}\n\n.inline-toggle .toggle-btn:hover {\n color: #333;\n}\n\n.inline-toggle .toggle-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* ============================================\n COMPACT ENTITY CARDS (Recent/Favorites rows)\n ============================================ */\n\n.entity-card-row {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding: 0;\n}\n\n.entity-card.compact {\n flex: 0 0 auto;\n width: auto;\n min-width: 180px;\n max-width: 280px;\n padding: 12px 16px;\n gap: 12px;\n}\n\n.entity-card.compact .entity-card-icon {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n}\n\n.entity-card.compact .entity-card-icon i {\n font-size: 16px;\n}\n\n.entity-card.compact .entity-card-title {\n margin: 0;\n font-size: 14px;\n}\n\n.entity-card.compact .entity-card-content {\n display: flex;\n align-items: center;\n}\n\n/* ============================================\n FAVORITE BUTTON\n ============================================ */\n\n.favorite-btn {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #ccc;\n transition: all 0.15s ease;\n margin-left: auto;\n}\n\n.favorite-btn:hover {\n background: rgba(255, 193, 7, 0.1);\n color: #ffc107;\n transform: scale(1.1);\n}\n\n.favorite-btn.favorited {\n color: #ffc107;\n}\n\n.favorite-btn.favorited:hover {\n background: rgba(255, 193, 7, 0.15);\n color: #ffb300;\n}\n\n.entity-card .favorite-btn {\n opacity: 0;\n transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;\n}\n\n.entity-card:hover .favorite-btn {\n opacity: 1;\n}\n\n.entity-card .favorite-btn.favorited {\n opacity: 1;\n}\n\n/* ============================================\n RECENT RECORDS LIST\n ============================================ */\n\n.recent-records-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.recent-record-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.recent-record-item:hover {\n background: #f5f7fa;\n}\n\n.recent-record-icon {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e8f5e9, #c8e6c9);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.recent-record-icon i {\n font-size: 14px;\n color: #4caf50;\n}\n\n.recent-record-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.recent-record-name {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recent-record-entity {\n font-size: 12px;\n color: #888;\n}\n\n.recent-record-time {\n font-size: 11px;\n color: #aaa;\n flex-shrink: 0;\n}\n\n/* ============================================\n ENTITY LIST (for Recent/Favorite Entities)\n ============================================ */\n\n.entity-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.entity-list-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.entity-list-item:hover {\n background: #f5f7fa;\n}\n\n.entity-list-icon {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-list-icon i {\n font-size: 14px;\n color: #1976d2;\n}\n\n.entity-list-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.entity-list-name {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-list-item .favorite-btn {\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.entity-list-item:hover .favorite-btn {\n opacity: 1;\n}\n\n.entity-list-item .favorite-btn.favorited {\n opacity: 1;\n}\n\n/* ============================================\n ENTITY FILTER STRIP (for Recent Records)\n ============================================ */\n\n.entity-filter-strip {\n display: flex;\n gap: 4px;\n margin-left: auto;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 3px;\n}\n\n.entity-filter-btn {\n width: 28px;\n height: 26px;\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: #666;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.entity-filter-btn:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.entity-filter-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* ============================================\n COMMON/ALL TOGGLE WITH LABELS\n ============================================ */\n\n.view-mode-toggle .toggle-btn {\n width: auto;\n padding: 0 12px;\n gap: 6px;\n}\n\n.toggle-label {\n font-size: 12px;\n font-weight: 500;\n}\n\n/* ============================================\n EMPTY STATE VARIANTS\n ============================================ */\n\n.empty-state.small {\n height: auto;\n padding: 32px;\n background: #fafafa;\n}\n\n.empty-state.small .empty-icon {\n font-size: 40px;\n margin-bottom: 16px;\n}\n\n.empty-state.small h3 {\n font-size: 16px;\n}\n\n.empty-state.small p {\n font-size: 13px;\n}\n\n/* ============================================\n RESPONSIVE STYLES\n ============================================ */\n\n@media (max-width: 1200px) {\n .entity-card-grid {\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n }\n}\n\n@media (max-width: 900px) {\n .content-header {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .header-center {\n order: 3;\n flex-basis: 100%;\n max-width: 100%;\n }\n\n .entity-card.compact {\n min-width: 160px;\n }\n\n /* Stack two-column layout on smaller screens */\n .home-two-column-layout {\n grid-template-columns: 1fr;\n gap: 20px;\n }\n}\n\n@media (max-width: 600px) {\n .data-explorer-container {\n flex-direction: column;\n }\n\n .navigation-panel {\n display: none;\n }\n\n .content-header {\n padding: 12px 16px;\n }\n\n .content-body {\n padding: 12px 16px;\n }\n\n .entity-card-grid {\n grid-template-columns: 1fr;\n gap: 12px;\n }\n\n .entity-card {\n padding: 16px;\n }\n\n .entity-card.compact {\n min-width: 100%;\n max-width: 100%;\n }\n\n .entity-card-row {\n flex-direction: column;\n }\n\n .view-mode-toggle {\n display: none;\n }\n\n .section-title {\n font-size: 13px;\n }\n\n .home-section {\n margin-bottom: 20px;\n }\n}\n"] }]
|
|
2101
|
-
}], () => [{ type: i1.ExplorerStateService }, { type: i0.ChangeDetectorRef }, { type: i2.Router }, { type: i3.RecentAccessService }], { filterInputRef: [{
|
|
2405
|
+
], template: "<div class=\"data-explorer-container\">\n <!-- Navigation Panel (Left) - Hidden at home level, animated -->\n @if (!isAtHomeLevel) {\n <div\n class=\"navigation-panel\"\n [class.collapsed]=\"state.navigationPanelCollapsed\"\n [style.width.px]=\"state.navigationPanelCollapsed ? 48 : state.navigationPanelWidth\"\n [@slideInLeft]>\n\n <mj-explorer-navigation-panel\n [entities]=\"entities\"\n [selectedEntityName]=\"state.selectedEntityName\"\n [favorites]=\"state.favorites\"\n [recentItems]=\"state.recentItems\"\n [collapsed]=\"state.navigationPanelCollapsed\"\n [allowedEntityNames]=\"allowedEntityNames\"\n [favoritesSectionExpanded]=\"state.favoritesSectionExpanded\"\n [recentSectionExpanded]=\"state.recentSectionExpanded\"\n [entitiesSectionExpanded]=\"state.entitiesSectionExpanded\"\n [viewsSectionExpanded]=\"state.viewsSectionExpanded\"\n (entitySelected)=\"onEntitySelected($event)\"\n (toggleCollapse)=\"toggleNavigationPanel()\"\n (sectionToggled)=\"stateService.toggleSection($event)\"\n (openRecord)=\"onOpenRecordFromNav($event)\"\n (selectRecord)=\"onSelectRecordFromNav($event)\"\n (expandAndFocus)=\"onExpandAndFocus($event)\">\n </mj-explorer-navigation-panel>\n </div>\n }\n\n <!-- Main Content Area -->\n <div class=\"content-area\">\n <!-- Breadcrumb Bar - Hidden at home level -->\n @if (!isAtHomeLevel && breadcrumbs.length > 0) {\n <div class=\"breadcrumb-bar\">\n @for (crumb of breadcrumbs; track crumb.label; let i = $index; let last = $last) {\n <span\n class=\"breadcrumb-item\"\n [class.clickable]=\"!last\"\n [class.current]=\"last\"\n (click)=\"onBreadcrumbClick(crumb, i)\"\n [title]=\"crumb.label\">\n @if (crumb.icon) {\n <i [class]=\"crumb.icon\" class=\"breadcrumb-icon\"></i>\n }\n <span class=\"breadcrumb-label\">{{ crumb.label }}</span>\n </span>\n @if (!last) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n }\n }\n </div>\n }\n\n <!-- Header -->\n <div class=\"content-header\" [class.home-header]=\"isAtHomeLevel\">\n <div class=\"header-left\">\n @if (selectedEntity) {\n <i [class]=\"getEntityIcon(selectedEntity)\" class=\"entity-icon\"></i>\n <h2 class=\"entity-title\">{{ selectedEntity.Name }}</h2>\n @if (debouncedFilterText && filteredRecordCount !== totalRecordCount) {\n <span class=\"record-count\">{{ filteredRecordCount | number }} of {{ totalRecordCount | number }} records</span>\n } @else {\n <span class=\"record-count\">{{ totalRecordCount | number }} records</span>\n }\n\n <!-- View Selector -->\n <mj-view-selector\n [entity]=\"selectedEntity\"\n [selectedViewId]=\"state.selectedViewId\"\n [viewModified]=\"state.viewModified\"\n (viewSelected)=\"onViewSelected($event)\"\n (saveViewRequested)=\"onSaveViewRequested($event)\"\n (manageViewsRequested)=\"onManageViewsRequested()\"\n (openInTabRequested)=\"onOpenInTabRequested($event)\"\n (configureViewRequested)=\"onConfigureViewRequested()\">\n </mj-view-selector>\n } @else {\n @if (displayIcon) {\n <i [class]=\"displayIcon\" class=\"entity-icon\"></i>\n }\n <h2 class=\"entity-title\">{{ displayTitle }}</h2>\n <span class=\"record-count\">{{ entities.length }} entities available</span>\n }\n </div>\n\n <div class=\"header-center\">\n @if (selectedEntity) {\n <div class=\"smart-filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"smart-filter-input\"\n placeholder=\"Filter records... (press / to focus)\"\n [ngModel]=\"state.smartFilterPrompt\"\n (ngModelChange)=\"onSmartFilterChanged($event)\"\n />\n @if (state.smartFilterPrompt) {\n <button class=\"clear-filter-btn\" (click)=\"onSmartFilterChanged('')\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n } @else {\n <!-- Entity filter for home screen -->\n <div class=\"smart-filter-container\">\n <i class=\"fa-solid fa-search filter-icon\"></i>\n <input\n #filterInput\n type=\"text\"\n class=\"smart-filter-input\"\n placeholder=\"Filter entities... (press / to focus)\"\n [(ngModel)]=\"entityFilterText\"\n />\n @if (entityFilterText) {\n <button class=\"clear-filter-btn\" (click)=\"entityFilterText = ''\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n }\n </div>\n\n <div class=\"header-right\">\n @if (selectedEntity) {\n <!-- View Mode Toggle -->\n <div class=\"view-mode-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.viewMode === 'grid'\"\n (click)=\"onViewModeChanged('grid')\"\n title=\"Grid View\">\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.viewMode === 'cards'\"\n (click)=\"onViewModeChanged('cards')\"\n title=\"Cards View\">\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n @if (entityHasDateFields) {\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.viewMode === 'timeline'\"\n (click)=\"onViewModeChanged('timeline')\"\n title=\"Timeline View\">\n <i class=\"fa-solid fa-timeline\"></i>\n </button>\n }\n </div>\n\n <!-- Timeline Controls (only shown when timeline view is active) -->\n @if (state.viewMode === 'timeline' && entityHasDateFields) {\n <!-- Date Field Selector -->\n <div class=\"date-field-selector-container\">\n <!-- Backdrop for closing dropdown -->\n @if (isDateFieldDropdownOpen) {\n <div class=\"date-field-backdrop\" (click)=\"closeDateFieldDropdown()\"></div>\n }\n\n <div class=\"date-field-selector-wrapper\">\n <button\n class=\"date-field-selector-button\"\n [class.open]=\"isDateFieldDropdownOpen\"\n [disabled]=\"availableDateFields.length <= 1\"\n (click)=\"toggleDateFieldDropdown()\">\n <i class=\"fa-solid fa-calendar-days date-field-icon\"></i>\n <span class=\"date-field-name\">{{ effectiveTimelineDateFieldDisplayName }}</span>\n @if (availableDateFields.length > 1) {\n <i class=\"fa-solid fa-chevron-down date-field-arrow\" [class.rotated]=\"isDateFieldDropdownOpen\"></i>\n }\n </button>\n\n @if (isDateFieldDropdownOpen && availableDateFields.length > 1) {\n <div class=\"date-field-dropdown-panel\">\n @for (field of availableDateFields; track field.name) {\n <div\n class=\"date-field-dropdown-item\"\n [class.selected]=\"field.name === effectiveTimelineDateField\"\n (click)=\"setTimelineDateField(field.name)\">\n <i class=\"fa-regular fa-calendar item-icon\"></i>\n <span class=\"item-name\">{{ field.displayName }}</span>\n @if (field.name === effectiveTimelineDateField) {\n <i class=\"fa-solid fa-check selected-check\"></i>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Orientation Toggle -->\n <div class=\"timeline-orientation-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"toggleTimelineOrientation()\"\n [title]=\"state.timelineOrientation === 'vertical' ? 'Switch to Horizontal' : 'Switch to Vertical'\">\n <i [class]=\"state.timelineOrientation === 'vertical' ? 'fa-solid fa-ellipsis-vertical' : 'fa-solid fa-ellipsis'\"></i>\n </button>\n </div>\n\n <!-- Sort Order Toggle -->\n <div class=\"timeline-sort-toggle\">\n <button\n class=\"toggle-btn\"\n (click)=\"toggleTimelineSortOrder()\"\n [title]=\"state.timelineSortOrder === 'desc' ? 'Showing Newest First (click for Oldest First)' : 'Showing Oldest First (click for Newest First)'\">\n <i [class]=\"state.timelineSortOrder === 'desc' ? 'fa-solid fa-arrow-down-wide-short' : 'fa-solid fa-arrow-up-wide-short'\"></i>\n </button>\n </div>\n }\n }\n <!-- Common/All toggle moved to inline with All Entities section header -->\n </div>\n </div>\n\n <!-- Content Body - Using mj-entity-viewer composite -->\n <div class=\"content-body\" [class.home-content]=\"isAtHomeLevel\">\n @if (!selectedEntity) {\n <!-- Entity Home View - Two-Column Layout -->\n <div class=\"entity-home-view\">\n @if (isLoadingEntities) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading entities...\" size=\"medium\"></mj-loading>\n </div>\n } @else {\n <!-- Two-Column Layout: Records (left) | Entities (right) -->\n @if (hasTopSectionContent) {\n <div class=\"home-two-column-layout\" [class.single-column]=\"!hasRecordsColumnContent || !hasEntitiesColumnContent\">\n <!-- Left Column: Recent & Favorite Records (most actionable) -->\n @if (hasRecordsColumnContent) {\n <div class=\"home-column\">\n <!-- Recent Records Section -->\n @if (recentRecords.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-history section-icon\"></i>\n <h3 class=\"section-title\">Recent Records</h3>\n <!-- Entity filter strip - only show with 2+ entities -->\n @if (showRecentRecordsEntityFilter) {\n <div class=\"entity-filter-strip\">\n <button\n class=\"entity-filter-btn\"\n [class.active]=\"recentRecordsEntityFilter === null\"\n (click)=\"setRecentRecordsEntityFilter(null)\"\n title=\"Show all entities\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </button>\n @for (entity of uniqueRecentRecordEntities; track entity.entityId) {\n <button\n class=\"entity-filter-btn\"\n [class.active]=\"recentRecordsEntityFilter === entity.entityId\"\n (click)=\"setRecentRecordsEntityFilter(entity.entityId)\"\n [title]=\"entity.entityName\">\n <i [class]=\"entity.icon\"></i>\n </button>\n }\n </div>\n }\n </div>\n <div class=\"recent-records-list\">\n @for (record of filteredRecentRecords; track record.entityId + '|' + record.recordId) {\n <div\n class=\"recent-record-item\"\n (click)=\"onRecentRecordClick(record)\"\n [title]=\"record.entityName + ' - ' + record.recordId\">\n <div class=\"recent-record-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"recent-record-content\">\n <span class=\"recent-record-name\">{{ record.recordName || record.recordId }}</span>\n <span class=\"recent-record-entity\">{{ record.entityName }}</span>\n </div>\n <span class=\"recent-record-time\">{{ formatRelativeTime(record.latestAt) }}</span>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Favorite Records Section -->\n @if (favoriteRecords.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <h3 class=\"section-title\">Favorite Records</h3>\n </div>\n <div class=\"recent-records-list\">\n @for (record of favoriteRecords; track record.userFavoriteId) {\n <div\n class=\"recent-record-item\"\n (click)=\"onFavoriteRecordClick(record)\"\n [title]=\"record.entityName + ' - ' + record.recordId\">\n <div class=\"recent-record-icon\">\n <i [class]=\"getEntityIconById(record.entityId)\"></i>\n </div>\n <div class=\"recent-record-content\">\n <span class=\"recent-record-name\">{{ record.recordName || record.recordId }}</span>\n <span class=\"recent-record-entity\">{{ record.entityName }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Right Column: Recent & Favorite Entities -->\n @if (hasEntitiesColumnContent) {\n <div class=\"home-column\">\n <!-- Recent Entities Section (list format) -->\n @if (recentEntities.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-clock section-icon\"></i>\n <h3 class=\"section-title\">Recent Entities</h3>\n </div>\n <div class=\"entity-list\">\n @for (entity of recentEntities; track entity.ID) {\n <div\n class=\"entity-list-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.Name\">\n <div class=\"entity-list-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-list-content\">\n <span class=\"entity-list-name\">{{ entity.Name }}</span>\n </div>\n <button\n class=\"favorite-btn\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Favorite Entities Section (list format) -->\n @if (favoriteEntities.length > 0) {\n <div class=\"home-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star section-icon\"></i>\n <h3 class=\"section-title\">Favorite Entities</h3>\n </div>\n <div class=\"entity-list\">\n @for (entity of favoriteEntities; track entity.ID) {\n <div\n class=\"entity-list-item\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.Name\">\n <div class=\"entity-list-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-list-content\">\n <span class=\"entity-list-name\">{{ entity.Name }}</span>\n </div>\n <button\n class=\"favorite-btn favorited\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n title=\"Remove from favorites\">\n <i class=\"fa-solid fa-star\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- All/Common Entities Section - Full Width -->\n <div class=\"home-section\">\n <div class=\"section-header-with-toggle\">\n <div class=\"section-header-left\">\n <i class=\"fa-solid fa-database section-icon\"></i>\n <h3 class=\"section-title\">\n @if (state.showAllEntities || !showCommonAllToggle) {\n All Entities\n } @else {\n Common Entities\n }\n </h3>\n @if (entityFilterText && filteredEntities.length !== entities.length) {\n <span class=\"section-count\">{{ filteredEntities.length }} matching</span>\n }\n </div>\n @if (showCommonAllToggle) {\n <div class=\"inline-toggle\">\n <button\n class=\"toggle-btn\"\n [class.active]=\"!state.showAllEntities\"\n (click)=\"toggleShowAllEntities()\"\n title=\"Show common entities ({{ commonEntitiesCount }})\">\n Common\n </button>\n <button\n class=\"toggle-btn\"\n [class.active]=\"state.showAllEntities\"\n (click)=\"toggleShowAllEntities()\"\n title=\"Show all entities ({{ allEntitiesCount }})\">\n All\n </button>\n </div>\n }\n </div>\n <div class=\"entity-card-grid\">\n @for (entity of filteredEntities; track entity.ID) {\n <div\n class=\"entity-card\"\n (click)=\"onEntitySelected(entity)\"\n [title]=\"entity.Description || entity.Name\">\n <div class=\"entity-card-icon\">\n <i [class]=\"getEntityIcon(entity)\"></i>\n </div>\n <div class=\"entity-card-content\">\n <h4 class=\"entity-card-title\">{{ entity.Name }}</h4>\n @if (entity.Description) {\n <p class=\"entity-card-description\">{{ entity.Description }}</p>\n }\n </div>\n <button\n class=\"favorite-btn\"\n [class.favorited]=\"isEntityFavorited(entity)\"\n (click)=\"toggleEntityFavorite(entity, $event)\"\n [title]=\"isEntityFavorited(entity) ? 'Remove from favorites' : 'Add to favorites'\">\n <i [class]=\"isEntityFavorited(entity) ? 'fa-solid fa-star' : 'fa-regular fa-star'\"></i>\n </button>\n </div>\n }\n </div>\n @if (filteredEntities.length === 0 && entities.length > 0) {\n <div class=\"empty-state small\">\n <i class=\"fa-solid fa-search empty-icon\"></i>\n <h3>No Matching Entities</h3>\n <p>No entities match \"{{ entityFilterText }}\"</p>\n </div>\n }\n @if (entities.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-database empty-icon\"></i>\n <h3>No Entities Available</h3>\n <p>There are no entities configured for this application.</p>\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <mj-entity-viewer\n [entity]=\"selectedEntity\"\n [viewEntity]=\"selectedViewEntity\"\n [viewMode]=\"state.viewMode\"\n [filterText]=\"debouncedFilterText\"\n [selectedRecordId]=\"state.selectedRecordId\"\n [config]=\"viewerConfig\"\n [gridState]=\"currentGridState\"\n [timelineConfig]=\"currentTimelineConfig\"\n (viewModeChange)=\"onViewModeChanged($event)\"\n (filterTextChange)=\"onFilterTextChanged($event)\"\n (recordSelected)=\"onViewerRecordSelected($event)\"\n (recordOpened)=\"onViewerRecordOpened($event)\"\n (dataLoaded)=\"onDataLoaded($event)\"\n (filteredCountChanged)=\"onFilteredCountChanged($event)\"\n (gridStateChanged)=\"onGridStateChanged($event)\">\n </mj-entity-viewer>\n }\n </div>\n </div>\n\n <!-- Detail Panel (Right - Slide In) -->\n @if (state.detailPanelOpen && selectedRecord) {\n <div class=\"detail-panel\" [style.width.px]=\"state.detailPanelWidth\">\n <mj-entity-record-detail-panel\n [entity]=\"detailPanelEntity\"\n [record]=\"selectedRecord\"\n (close)=\"onDetailPanelClosed()\"\n (openRecord)=\"onOpenRecord($event)\"\n (navigateToRelated)=\"onNavigateToRelated($event)\"\n (openRelatedRecord)=\"onOpenRelatedRecord($event)\"\n (openForeignKeyRecord)=\"onOpenForeignKeyRecord($event)\">\n </mj-entity-record-detail-panel>\n </div>\n }\n\n <!-- View Configuration Panel -->\n <mj-view-config-panel\n [entity]=\"selectedEntity\"\n [viewEntity]=\"selectedViewEntity\"\n [isOpen]=\"state.viewConfigPanelOpen\"\n [currentGridState]=\"currentGridState\"\n [externalFilterState]=\"filterDialogState\"\n (close)=\"onCloseViewConfigPanel()\"\n (save)=\"onSaveView($event)\"\n (delete)=\"onDeleteView()\"\n (openFilterDialogRequest)=\"onOpenFilterDialogRequest($event)\">\n </mj-view-config-panel>\n\n <!-- Filter Dialog (rendered at dashboard level for full viewport width) -->\n <mj-filter-dialog\n [isOpen]=\"isFilterDialogOpen\"\n [fields]=\"filterDialogFields\"\n [filter]=\"filterDialogState\"\n [disabled]=\"filterDialogDisabled\"\n (close)=\"onCloseFilterDialog()\"\n (apply)=\"onFilterApplied($event)\">\n </mj-filter-dialog>\n</div>\n", styles: [".data-explorer-container {\n display: flex;\n height: 100%;\n width: 100%;\n background: #f5f7fa;\n overflow: hidden;\n}\n\n.navigation-panel {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-right: 1px solid #e0e0e0;\n transition: width 0.2s ease-in-out;\n overflow: hidden;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04);\n}\n.navigation-panel.collapsed {\n width: 48px;\n}\n\n.content-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-width: 0;\n overflow: hidden;\n background: #f5f7fa;\n}\n\n/* Breadcrumb Bar */\n.breadcrumb-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 24px;\n background: white;\n border-bottom: 1px solid #eee;\n flex-shrink: 0;\n font-size: 13px;\n min-height: 40px;\n}\n\n.breadcrumb-item {\n display: flex;\n align-items: center;\n gap: 6px;\n color: #666;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s ease;\n max-width: 200px;\n}\n\n.breadcrumb-item.clickable {\n cursor: pointer;\n}\n\n.breadcrumb-item.clickable:hover {\n background: #f0f0f0;\n color: #1976d2;\n}\n\n.breadcrumb-item.current {\n color: #1a1a1a;\n font-weight: 500;\n cursor: default;\n}\n\n.breadcrumb-icon {\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.breadcrumb-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.breadcrumb-separator {\n font-size: 10px;\n color: #ccc;\n flex-shrink: 0;\n}\n\n.content-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n gap: 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n flex-wrap: wrap;\n}\n\n/* View Selector within header */\n.header-left ::ng-deep mj-view-selector {\n margin-left: 8px;\n}\n\n.entity-icon {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-title {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #1a1a1a;\n}\n\n.record-count {\n font-size: 13px;\n color: #666;\n font-weight: 500;\n}\n\n.header-center {\n flex: 1;\n max-width: 600px;\n}\n\n.smart-filter-container {\n position: relative;\n width: 100%;\n}\n\n.smart-filter-input {\n width: 100%;\n padding: 10px 40px 10px 16px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n font-size: 14px;\n background: #fafafa;\n transition: all 0.15s ease;\n}\n.smart-filter-input:focus {\n outline: none;\n border-color: #1976d2;\n background: white;\n box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);\n}\n.smart-filter-input::placeholder {\n color: #999;\n}\n\n.clear-filter-btn {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #757575;\n transition: all 0.15s ease;\n}\n.clear-filter-btn:hover {\n background: #e0e0e0;\n color: #424242;\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 16px;\n flex-shrink: 0;\n}\n\n.view-mode-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 8px;\n padding: 3px;\n}\n\n.toggle-btn {\n width: 36px;\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: #666;\n transition: all 0.15s ease;\n}\n.toggle-btn:hover {\n color: #333;\n}\n.toggle-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Timeline Date Field Selector - Styled Dropdown */\n.date-field-selector-container {\n display: flex;\n align-items: center;\n position: relative;\n}\n\n.date-field-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.date-field-selector-wrapper {\n position: relative;\n}\n\n.date-field-selector-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--background-alt, #f5f5f5);\n border: 1px solid var(--border-color, #e0e0e0);\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n color: var(--text-primary, #333);\n transition: all 0.15s ease;\n min-width: 120px;\n max-width: 200px;\n}\n\n.date-field-selector-button:hover:not(:disabled) {\n background: var(--background-hover, #e8e8e8);\n border-color: var(--border-color-hover, #ccc);\n}\n\n.date-field-selector-button:disabled {\n cursor: default;\n opacity: 0.8;\n}\n\n.date-field-selector-button.open {\n background: var(--background-active, #e0e0e0);\n border-color: var(--primary-color, #007bff);\n}\n\n.date-field-icon {\n color: var(--text-secondary, #666);\n font-size: 12px;\n}\n\n.date-field-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.date-field-arrow {\n color: var(--text-secondary, #666);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.date-field-arrow.rotated {\n transform: rotate(180deg);\n}\n\n.date-field-dropdown-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n min-width: 180px;\n max-width: 280px;\n max-height: 300px;\n overflow-y: auto;\n background: var(--background-panel, #fff);\n border: 1px solid var(--border-color, #e0e0e0);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n z-index: 1000;\n}\n\n.date-field-dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n transition: background 0.1s ease;\n font-size: 13px;\n}\n\n.date-field-dropdown-item:hover {\n background: var(--background-hover, #f5f5f5);\n}\n\n.date-field-dropdown-item.selected {\n background: var(--primary-light, #e6f0ff);\n}\n\n.date-field-dropdown-item.selected:hover {\n background: var(--primary-light-hover, #d6e4f9);\n}\n\n.date-field-dropdown-item .item-icon {\n color: var(--text-secondary, #666);\n font-size: 13px;\n width: 16px;\n text-align: center;\n}\n\n.date-field-dropdown-item .item-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.date-field-dropdown-item .selected-check {\n color: var(--primary-color, #007bff);\n font-size: 12px;\n}\n\n/* Timeline Orientation Toggle */\n.timeline-orientation-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 8px;\n padding: 3px;\n}\n\n.content-body {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n display: flex;\n flex-direction: column;\n}\n\n.loading-container,\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 16px;\n background: white;\n border-radius: 8px;\n}\n\n.loading-spinner {\n font-size: 32px;\n color: #1976d2;\n}\n\n.loading-message {\n margin: 0;\n font-size: 14px;\n color: #666;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n text-align: center;\n color: #757575;\n background: white;\n border-radius: 8px;\n padding: 40px;\n}\n\n.empty-icon {\n font-size: 64px;\n color: #e0e0e0;\n margin-bottom: 24px;\n}\n\n.empty-state h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n color: #666;\n}\n\n/* Entity Home View - Card Grid */\n.entity-home-view {\n flex: 1;\n overflow: auto;\n padding: 4px;\n}\n\n.entity-card-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 16px;\n padding: 0;\n}\n\n.entity-card {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 1px solid #e8e8e8;\n}\n\n.entity-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);\n border-color: #1976d2;\n}\n\n.entity-card:active {\n transform: translateY(0);\n}\n\n.entity-card-icon {\n width: 48px;\n height: 48px;\n border-radius: 10px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-card-icon i {\n font-size: 20px;\n color: #1976d2;\n}\n\n.entity-card:hover .entity-card-icon {\n background: linear-gradient(135deg, #1976d2, #1565c0);\n}\n\n.entity-card:hover .entity-card-icon i {\n color: white;\n}\n\n.entity-card-content {\n flex: 1;\n min-width: 0;\n}\n\n.entity-card-title {\n margin: 0 0 6px 0;\n font-size: 15px;\n font-weight: 600;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-card-description {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.detail-panel {\n flex-shrink: 0;\n height: 100%;\n background: white;\n border-left: 1px solid #e0e0e0;\n box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n animation: slideIn 0.2s ease-out;\n}\n\n@keyframes slideIn {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n:host ::ng-deep mj-explorer-grid-view,\n:host ::ng-deep mj-explorer-cards-view {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n/* ============================================\n HOME SCREEN STYLES\n ============================================ */\n\n/* Home-level header adjustments */\n.content-header.home-header {\n border-bottom: none;\n background: transparent;\n box-shadow: none;\n padding: 24px 24px 16px;\n}\n\n.content-body.home-content {\n padding-top: 0;\n}\n\n/* Smart filter with search icon */\n.filter-icon {\n position: absolute;\n left: 14px;\n top: 50%;\n transform: translateY(-50%);\n color: #999;\n font-size: 14px;\n pointer-events: none;\n}\n\n.smart-filter-container .smart-filter-input {\n padding-left: 40px;\n}\n\n/* ============================================\n HOME SECTIONS\n ============================================ */\n\n.home-section {\n margin-bottom: 28px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-icon {\n font-size: 14px;\n color: #1976d2;\n width: 20px;\n text-align: center;\n}\n\n.section-title {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-count {\n font-size: 12px;\n color: #888;\n font-weight: 500;\n margin-left: 8px;\n}\n\n/* ============================================\n TWO-COLUMN LAYOUT (Entities left, Records right)\n ============================================ */\n\n.home-two-column-layout {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 24px;\n margin-bottom: 28px;\n}\n\n/* When only one column has content, let it take full width */\n.home-two-column-layout.single-column {\n grid-template-columns: 1fr;\n}\n\n.home-column {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n/* Section header with inline toggle */\n.section-header-with-toggle {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 14px;\n padding-left: 4px;\n}\n\n.section-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n/* Inline Common/All toggle (compact) */\n.inline-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.inline-toggle .toggle-btn {\n width: auto;\n height: 26px;\n padding: 0 10px;\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: #666;\n font-size: 11px;\n font-weight: 500;\n transition: all 0.15s ease;\n}\n\n.inline-toggle .toggle-btn:hover {\n color: #333;\n}\n\n.inline-toggle .toggle-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* ============================================\n COMPACT ENTITY CARDS (Recent/Favorites rows)\n ============================================ */\n\n.entity-card-row {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding: 0;\n}\n\n.entity-card.compact {\n flex: 0 0 auto;\n width: auto;\n min-width: 180px;\n max-width: 280px;\n padding: 12px 16px;\n gap: 12px;\n}\n\n.entity-card.compact .entity-card-icon {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n}\n\n.entity-card.compact .entity-card-icon i {\n font-size: 16px;\n}\n\n.entity-card.compact .entity-card-title {\n margin: 0;\n font-size: 14px;\n}\n\n.entity-card.compact .entity-card-content {\n display: flex;\n align-items: center;\n}\n\n/* ============================================\n FAVORITE BUTTON\n ============================================ */\n\n.favorite-btn {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #ccc;\n transition: all 0.15s ease;\n margin-left: auto;\n}\n\n.favorite-btn:hover {\n background: rgba(255, 193, 7, 0.1);\n color: #ffc107;\n transform: scale(1.1);\n}\n\n.favorite-btn.favorited {\n color: #ffc107;\n}\n\n.favorite-btn.favorited:hover {\n background: rgba(255, 193, 7, 0.15);\n color: #ffb300;\n}\n\n.entity-card .favorite-btn {\n opacity: 0;\n transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;\n}\n\n.entity-card:hover .favorite-btn {\n opacity: 1;\n}\n\n.entity-card .favorite-btn.favorited {\n opacity: 1;\n}\n\n/* ============================================\n RECENT RECORDS LIST\n ============================================ */\n\n.recent-records-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.recent-record-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.recent-record-item:hover {\n background: #f5f7fa;\n}\n\n.recent-record-icon {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e8f5e9, #c8e6c9);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.recent-record-icon i {\n font-size: 14px;\n color: #4caf50;\n}\n\n.recent-record-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.recent-record-name {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.recent-record-entity {\n font-size: 12px;\n color: #888;\n}\n\n.recent-record-time {\n font-size: 11px;\n color: #aaa;\n flex-shrink: 0;\n}\n\n/* ============================================\n ENTITY LIST (for Recent/Favorite Entities)\n ============================================ */\n\n.entity-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n background: white;\n border-radius: 10px;\n padding: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.entity-list-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.entity-list-item:hover {\n background: #f5f7fa;\n}\n\n.entity-list-icon {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n background: linear-gradient(135deg, #e3f2fd, #bbdefb);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.entity-list-icon i {\n font-size: 14px;\n color: #1976d2;\n}\n\n.entity-list-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.entity-list-name {\n font-size: 14px;\n font-weight: 500;\n color: #1a1a1a;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.entity-list-item .favorite-btn {\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.entity-list-item:hover .favorite-btn {\n opacity: 1;\n}\n\n.entity-list-item .favorite-btn.favorited {\n opacity: 1;\n}\n\n/* ============================================\n ENTITY FILTER STRIP (for Recent Records)\n ============================================ */\n\n.entity-filter-strip {\n display: flex;\n gap: 4px;\n margin-left: auto;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 3px;\n}\n\n.entity-filter-btn {\n width: 28px;\n height: 26px;\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: #666;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.entity-filter-btn:hover {\n color: #333;\n background: rgba(0, 0, 0, 0.05);\n}\n\n.entity-filter-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* ============================================\n COMMON/ALL TOGGLE WITH LABELS\n ============================================ */\n\n.view-mode-toggle .toggle-btn {\n width: auto;\n padding: 0 12px;\n gap: 6px;\n}\n\n.toggle-label {\n font-size: 12px;\n font-weight: 500;\n}\n\n/* ============================================\n EMPTY STATE VARIANTS\n ============================================ */\n\n.empty-state.small {\n height: auto;\n padding: 32px;\n background: #fafafa;\n}\n\n.empty-state.small .empty-icon {\n font-size: 40px;\n margin-bottom: 16px;\n}\n\n.empty-state.small h3 {\n font-size: 16px;\n}\n\n.empty-state.small p {\n font-size: 13px;\n}\n\n/* ============================================\n RESPONSIVE STYLES\n ============================================ */\n\n@media (max-width: 1200px) {\n .entity-card-grid {\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n }\n}\n\n@media (max-width: 900px) {\n .content-header {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .header-center {\n order: 3;\n flex-basis: 100%;\n max-width: 100%;\n }\n\n .entity-card.compact {\n min-width: 160px;\n }\n\n /* Stack two-column layout on smaller screens */\n .home-two-column-layout {\n grid-template-columns: 1fr;\n gap: 20px;\n }\n}\n\n@media (max-width: 600px) {\n .data-explorer-container {\n flex-direction: column;\n }\n\n .navigation-panel {\n display: none;\n }\n\n .content-header {\n padding: 12px 16px;\n }\n\n .content-body {\n padding: 12px 16px;\n }\n\n .entity-card-grid {\n grid-template-columns: 1fr;\n gap: 12px;\n }\n\n .entity-card {\n padding: 16px;\n }\n\n .entity-card.compact {\n min-width: 100%;\n max-width: 100%;\n }\n\n .entity-card-row {\n flex-direction: column;\n }\n\n .view-mode-toggle {\n display: none;\n }\n\n .section-title {\n font-size: 13px;\n }\n\n .home-section {\n margin-bottom: 20px;\n }\n}\n"] }]
|
|
2406
|
+
}], () => [{ type: i1.ExplorerStateService }, { type: i0.ChangeDetectorRef }, { type: i2.Router }, { type: i3.RecentAccessService }, { type: i4.NavigationService }], { filterInputRef: [{
|
|
2102
2407
|
type: ViewChild,
|
|
2103
2408
|
args: ['filterInput']
|
|
2104
2409
|
}], viewSelectorRef: [{
|
|
@@ -2107,6 +2412,9 @@ export { DataExplorerDashboardComponent };
|
|
|
2107
2412
|
}], entityViewerRef: [{
|
|
2108
2413
|
type: ViewChild,
|
|
2109
2414
|
args: [EntityViewerComponent]
|
|
2415
|
+
}], viewConfigPanelRef: [{
|
|
2416
|
+
type: ViewChild,
|
|
2417
|
+
args: [ViewConfigPanelComponent]
|
|
2110
2418
|
}], entityFilter: [{
|
|
2111
2419
|
type: Input
|
|
2112
2420
|
}], deepLink: [{
|
|
@@ -2119,7 +2427,7 @@ export { DataExplorerDashboardComponent };
|
|
|
2119
2427
|
type: HostListener,
|
|
2120
2428
|
args: ['document:keydown', ['$event']]
|
|
2121
2429
|
}] }); })();
|
|
2122
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DataExplorerDashboardComponent, { className: "DataExplorerDashboardComponent", filePath: "src/DataExplorer/data-explorer-dashboard.component.ts", lineNumber:
|
|
2430
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DataExplorerDashboardComponent, { className: "DataExplorerDashboardComponent", filePath: "src/DataExplorer/data-explorer-dashboard.component.ts", lineNumber: 56 }); })();
|
|
2123
2431
|
/**
|
|
2124
2432
|
* Tree-shaking prevention
|
|
2125
2433
|
*/
|