@memberjunction/ng-dashboards 6.2.0-edge.2 → 6.2.0-edge.4
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/AI/components/analytics/realtime/realtime-transcripts-data.d.ts +4 -3
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js +8 -5
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js.map +1 -1
- package/dist/AI/components/duplicates/compare-value.component.d.ts +67 -0
- package/dist/AI/components/duplicates/compare-value.component.d.ts.map +1 -0
- package/dist/AI/components/duplicates/compare-value.component.js +168 -0
- package/dist/AI/components/duplicates/compare-value.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +49 -3
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +287 -169
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +77 -0
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +116 -0
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -0
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +16 -4
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +2 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +12 -6
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-index-auto.d.ts +29 -0
- package/dist/AI/components/vectors/vector-index-auto.d.ts.map +1 -0
- package/dist/AI/components/vectors/vector-index-auto.js +59 -0
- package/dist/AI/components/vectors/vector-index-auto.js.map +1 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +9 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +65 -20
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +7 -3
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +3 -2
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts +0 -3
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +5 -14
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +1 -0
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +1 -0
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/form-override-dialog.component.d.ts +12 -1
- package/dist/ComponentStudio/components/form-override-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/form-override-dialog.component.js +128 -81
- package/dist/ComponentStudio/components/form-override-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +12 -10
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts +14 -43
- package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-agent-context.js +6 -29
- package/dist/DashboardBrowser/dashboard-browser-agent-context.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +174 -321
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +522 -1195
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-library-filter.d.ts +116 -0
- package/dist/DashboardBrowser/dashboard-library-filter.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboard-library-filter.js +277 -0
- package/dist/DashboardBrowser/dashboard-library-filter.js.map +1 -0
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboards-agent-tools.d.ts +26 -0
- package/dist/DashboardBrowser/dashboards-agent-tools.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboards-agent-tools.js +32 -0
- package/dist/DashboardBrowser/dashboards-agent-tools.js.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts +58 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.js +391 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.js.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts +37 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.js +68 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.js.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.component.d.ts +295 -0
- package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.component.js +1022 -0
- package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.types.d.ts +23 -0
- package/dist/DashboardEditor/dashboard-editor.types.d.ts.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.types.js +3 -0
- package/dist/DashboardEditor/dashboard-editor.types.js.map +1 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.d.ts +11 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.d.ts.map +1 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.js +17 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.js.map +1 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +30 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +349 -232
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +2 -5
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.d.ts +0 -14
- package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.js +7 -29
- package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
- package/dist/Home/home-agent-context.d.ts +29 -10
- package/dist/Home/home-agent-context.d.ts.map +1 -1
- package/dist/Home/home-agent-context.js +50 -24
- package/dist/Home/home-agent-context.js.map +1 -1
- package/dist/Home/home-dashboard-switcher.component.d.ts +95 -0
- package/dist/Home/home-dashboard-switcher.component.d.ts.map +1 -0
- package/dist/Home/home-dashboard-switcher.component.js +442 -0
- package/dist/Home/home-dashboard-switcher.component.js.map +1 -0
- package/dist/Home/home-dashboard.component.d.ts +330 -17
- package/dist/Home/home-dashboard.component.d.ts.map +1 -1
- package/dist/Home/home-dashboard.component.js +1702 -1014
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Home/home-menus.d.ts +38 -0
- package/dist/Home/home-menus.d.ts.map +1 -0
- package/dist/Home/home-menus.js +53 -0
- package/dist/Home/home-menus.js.map +1 -0
- package/dist/Home/home-pinned-dashboards.d.ts +33 -0
- package/dist/Home/home-pinned-dashboards.d.ts.map +1 -0
- package/dist/Home/home-pinned-dashboards.js +76 -0
- package/dist/Home/home-pinned-dashboards.js.map +1 -0
- package/dist/PredictiveStudio/components/ps-production.component.d.ts +5 -1
- package/dist/PredictiveStudio/components/ps-production.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-production.component.js +64 -41
- package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +3 -2
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js +2 -2
- package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js.map +1 -1
- package/dist/TelephonyOperations/telephony-operations-agent-context.d.ts +107 -0
- package/dist/TelephonyOperations/telephony-operations-agent-context.d.ts.map +1 -0
- package/dist/TelephonyOperations/telephony-operations-agent-context.js +216 -0
- package/dist/TelephonyOperations/telephony-operations-agent-context.js.map +1 -0
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts +58 -0
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts.map +1 -0
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.js +812 -0
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.js.map +1 -0
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +7 -7
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/WorkQueue/components/work-queue-bindings.component.d.ts +37 -0
- package/dist/WorkQueue/components/work-queue-bindings.component.d.ts.map +1 -0
- package/dist/WorkQueue/components/work-queue-bindings.component.js +210 -0
- package/dist/WorkQueue/components/work-queue-bindings.component.js.map +1 -0
- package/dist/WorkQueue/components/work-queue-dead-letters.component.d.ts +70 -0
- package/dist/WorkQueue/components/work-queue-dead-letters.component.d.ts.map +1 -0
- package/dist/WorkQueue/components/work-queue-dead-letters.component.js +496 -0
- package/dist/WorkQueue/components/work-queue-dead-letters.component.js.map +1 -0
- package/dist/WorkQueue/components/work-queue-discard-dialog.component.d.ts +22 -0
- package/dist/WorkQueue/components/work-queue-discard-dialog.component.d.ts.map +1 -0
- package/dist/WorkQueue/components/work-queue-discard-dialog.component.js +99 -0
- package/dist/WorkQueue/components/work-queue-discard-dialog.component.js.map +1 -0
- package/dist/WorkQueue/components/work-queue-overview.component.d.ts +29 -0
- package/dist/WorkQueue/components/work-queue-overview.component.d.ts.map +1 -0
- package/dist/WorkQueue/components/work-queue-overview.component.js +278 -0
- package/dist/WorkQueue/components/work-queue-overview.component.js.map +1 -0
- package/dist/WorkQueue/components/work-queue-partitions.component.d.ts +59 -0
- package/dist/WorkQueue/components/work-queue-partitions.component.d.ts.map +1 -0
- package/dist/WorkQueue/components/work-queue-partitions.component.js +359 -0
- package/dist/WorkQueue/components/work-queue-partitions.component.js.map +1 -0
- package/dist/WorkQueue/services/work-queue-operator.service.d.ts +22 -0
- package/dist/WorkQueue/services/work-queue-operator.service.d.ts.map +1 -0
- package/dist/WorkQueue/services/work-queue-operator.service.js +44 -0
- package/dist/WorkQueue/services/work-queue-operator.service.js.map +1 -0
- package/dist/WorkQueue/work-queue-agent-context.d.ts +67 -0
- package/dist/WorkQueue/work-queue-agent-context.d.ts.map +1 -0
- package/dist/WorkQueue/work-queue-agent-context.js +119 -0
- package/dist/WorkQueue/work-queue-agent-context.js.map +1 -0
- package/dist/WorkQueue/work-queue-dashboard.component.d.ts +94 -0
- package/dist/WorkQueue/work-queue-dashboard.component.d.ts.map +1 -0
- package/dist/WorkQueue/work-queue-dashboard.component.js +545 -0
- package/dist/WorkQueue/work-queue-dashboard.component.js.map +1 -0
- package/dist/WorkQueue/work-queue-types.d.ts +40 -0
- package/dist/WorkQueue/work-queue-types.d.ts.map +1 -0
- package/dist/WorkQueue/work-queue-types.js +2 -0
- package/dist/WorkQueue/work-queue-types.js.map +1 -0
- package/dist/ai-dashboards.module.d.ts +21 -20
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +4 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +69 -61
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +29 -2
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +1 -1
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +3 -1
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/module.d.ts +14 -13
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +6 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +9 -0
- package/dist/public-api.js.map +1 -1
- package/dist/shared/dashboard-library-changes.d.ts +23 -0
- package/dist/shared/dashboard-library-changes.d.ts.map +1 -0
- package/dist/shared/dashboard-library-changes.js +26 -0
- package/dist/shared/dashboard-library-changes.js.map +1 -0
- package/dist/shared/dashboard-owner-names.d.ts +17 -0
- package/dist/shared/dashboard-owner-names.d.ts.map +1 -0
- package/dist/shared/dashboard-owner-names.js +65 -0
- package/dist/shared/dashboard-owner-names.js.map +1 -0
- package/dist/shared/dashboard-recents.d.ts +34 -0
- package/dist/shared/dashboard-recents.d.ts.map +1 -0
- package/dist/shared/dashboard-recents.js +87 -0
- package/dist/shared/dashboard-recents.js.map +1 -0
- package/dist/shared/dashboards-app-install.d.ts +59 -0
- package/dist/shared/dashboards-app-install.d.ts.map +1 -0
- package/dist/shared/dashboards-app-install.js +97 -0
- package/dist/shared/dashboards-app-install.js.map +1 -0
- package/dist/shared/dashboards-app.helpers.d.ts +42 -0
- package/dist/shared/dashboards-app.helpers.d.ts.map +1 -0
- package/dist/shared/dashboards-app.helpers.js +143 -0
- package/dist/shared/dashboards-app.helpers.js.map +1 -0
- package/dist/work-queue-dashboards.module.d.ts +23 -0
- package/dist/work-queue-dashboards.module.d.ts.map +1 -0
- package/dist/work-queue-dashboards.module.js +92 -0
- package/dist/work-queue-dashboards.module.js.map +1 -0
- package/package.json +73 -66
|
@@ -4,17 +4,24 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { Component, ViewChild, ChangeDetectionStrategy, inject } from '@angular/core';
|
|
7
|
+
import { Component, ViewChild, ChangeDetectionStrategy, ElementRef, inject } from '@angular/core';
|
|
8
8
|
import { Subject } from 'rxjs';
|
|
9
9
|
import { takeUntil } from 'rxjs/operators';
|
|
10
|
-
import { BaseResourceComponent, HomeAppPinService } from '@memberjunction/ng-shared';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { BaseResourceComponent, HomeAppPinService, IsDashboardEntity, SafeDetectChanges, BuildDashboardPinInput } from '@memberjunction/ng-shared';
|
|
11
|
+
import { ResourceTypeForEntity } from '@memberjunction/ng-shared-generic';
|
|
12
|
+
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
13
|
+
import { CompositeKey, LogError } from '@memberjunction/core';
|
|
13
14
|
import { UserInfoEngine, DashboardEngine, UserViewEngine, QueryEngine } from '@memberjunction/core-entities';
|
|
14
15
|
import { ActionEngineBase } from '@memberjunction/actions-base';
|
|
16
|
+
import { DASHBOARD_NAME_MAX_LENGTH } from '@memberjunction/ng-dashboard-viewer';
|
|
15
17
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
18
|
+
import { MJConfirmService } from '@memberjunction/ng-ui-components';
|
|
16
19
|
import { BuildHomeAgentContext, BuildHomeNotFoundError, ResolveNamedRecord } from './home-agent-context';
|
|
20
|
+
import { MenuAnchorOf, NextMenuFocusIndex, PlaceMenu } from './home-menus';
|
|
21
|
+
import { BuildPinDashboardNames, BuildPinnedDashboards, CanShowInHome, DashboardIdOfPin, FindDashboard, ResolvePinnedDashboardReference, ResolvePinResourceType, } from './home-pinned-dashboards';
|
|
17
22
|
import { ValidateStringParam } from '../shared/agent-tool-validation';
|
|
23
|
+
import { ObserveDashboardLibraryChanges } from '../shared/dashboard-library-changes';
|
|
24
|
+
import { AutoInstallDashboardsApp, CreateBlankDashboard, DashboardNameMaxLength, EnsureDashboardsApp } from '../shared/dashboards-app.helpers';
|
|
18
25
|
import * as i0 from "@angular/core";
|
|
19
26
|
import * as i1 from "@memberjunction/ng-base-application";
|
|
20
27
|
import * as i2 from "@memberjunction/ng-shared";
|
|
@@ -22,477 +29,480 @@ import * as i3 from "@angular/forms";
|
|
|
22
29
|
import * as i4 from "@memberjunction/ng-ui-components";
|
|
23
30
|
import * as i5 from "@memberjunction/ng-shared-generic";
|
|
24
31
|
import * as i6 from "@memberjunction/ng-explorer-settings";
|
|
25
|
-
import * as i7 from "
|
|
26
|
-
import * as i8 from "./
|
|
27
|
-
import * as i9 from "
|
|
32
|
+
import * as i7 from "@memberjunction/ng-dashboard-viewer";
|
|
33
|
+
import * as i8 from "./home-dashboard-switcher.component";
|
|
34
|
+
import * as i9 from "./action-pin-config-dialog.component";
|
|
35
|
+
import * as i10 from "./action-pin-runner-dialog.component";
|
|
36
|
+
import * as i11 from "../DashboardEditor/dashboard-editor.component";
|
|
37
|
+
import * as i12 from "@angular/common";
|
|
28
38
|
const _c0 = ["appConfigDialog"];
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
i0.ɵɵ
|
|
39
|
+
const _c1 = ["pinMenu"];
|
|
40
|
+
const _c2 = ["dashboardEditor"];
|
|
41
|
+
const _forTrack0 = ($index, $item) => $item.Key;
|
|
42
|
+
const _forTrack1 = ($index, $item) => $item.Id;
|
|
43
|
+
const _forTrack2 = ($index, $item) => $item.appId;
|
|
44
|
+
const _forTrack3 = ($index, $item) => $item.label;
|
|
45
|
+
const _forTrack4 = ($index, $item) => $item.id;
|
|
46
|
+
function HomeDashboardComponent_Conditional_2_ng_template_8_Template(rf, ctx) { if (rf & 1) {
|
|
47
|
+
i0.ɵɵelementStart(0, "span", 28);
|
|
48
|
+
i0.ɵɵelement(1, "i", 29);
|
|
49
|
+
i0.ɵɵtext(2, " Pinned");
|
|
38
50
|
i0.ɵɵelementEnd();
|
|
39
51
|
} }
|
|
40
|
-
function
|
|
52
|
+
function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
53
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
54
|
+
i0.ɵɵelementStart(0, "button", 32);
|
|
55
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.ToggleEditMode()); });
|
|
56
|
+
i0.ɵɵelement(1, "i", 33);
|
|
57
|
+
i0.ɵɵelementStart(2, "span", 34);
|
|
58
|
+
i0.ɵɵtext(3, "Done");
|
|
59
|
+
i0.ɵɵelementEnd()();
|
|
60
|
+
} }
|
|
61
|
+
function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
62
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
63
|
+
i0.ɵɵelementStart(0, "button", 39);
|
|
64
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.ToggleEditMode()); });
|
|
65
|
+
i0.ɵɵelement(1, "i", 40);
|
|
66
|
+
i0.ɵɵelementStart(2, "span", 34);
|
|
67
|
+
i0.ɵɵtext(3, "Edit");
|
|
68
|
+
i0.ɵɵelementEnd()();
|
|
69
|
+
} }
|
|
70
|
+
function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
41
71
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
42
|
-
i0.ɵɵelementStart(0, "button",
|
|
43
|
-
i0.ɵɵlistener("click", function
|
|
44
|
-
i0.ɵɵelement(1, "i",
|
|
45
|
-
i0.ɵɵ
|
|
72
|
+
i0.ɵɵelementStart(0, "button", 35);
|
|
73
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OpenAddPinPanel()); });
|
|
74
|
+
i0.ɵɵelement(1, "i", 36);
|
|
75
|
+
i0.ɵɵelementStart(2, "span", 34);
|
|
76
|
+
i0.ɵɵtext(3, "Add Pin");
|
|
77
|
+
i0.ɵɵelementEnd()();
|
|
78
|
+
i0.ɵɵelementStart(4, "mj-home-dashboard-switcher", 37);
|
|
79
|
+
i0.ɵɵlistener("Pick", function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Template_mj_home_dashboard_switcher_Pick_4_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnSwitcherPick($event)); })("New", function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Template_mj_home_dashboard_switcher_New_4_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OpenNewDashboardDialog()); })("ManagePins", function HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Template_mj_home_dashboard_switcher_ManagePins_4_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.ManagePins()); });
|
|
46
80
|
i0.ɵɵelementEnd();
|
|
81
|
+
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Conditional_5_Template, 4, 0, "button", 38);
|
|
82
|
+
} if (rf & 2) {
|
|
83
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
84
|
+
i0.ɵɵadvance(4);
|
|
85
|
+
i0.ɵɵproperty("Dashboards", ctx_r2.PinnedDashboards)("CurrentId", null);
|
|
86
|
+
i0.ɵɵadvance();
|
|
87
|
+
i0.ɵɵconditional(ctx_r2.PinnedItems.length > 0 ? 5 : -1);
|
|
47
88
|
} }
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
i0.ɵɵ
|
|
51
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_8_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OpenAddPinPanel()); });
|
|
52
|
-
i0.ɵɵelement(1, "i", 26);
|
|
53
|
-
i0.ɵɵtext(2, " Add Pin ");
|
|
89
|
+
function HomeDashboardComponent_Conditional_2_ng_template_9_Template(rf, ctx) { if (rf & 1) {
|
|
90
|
+
i0.ɵɵelementStart(0, "div", 30);
|
|
91
|
+
i0.ɵɵconditionalCreate(1, HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_1_Template, 4, 0, "button", 31)(2, HomeDashboardComponent_Conditional_2_ng_template_9_Conditional_2_Template, 6, 3);
|
|
54
92
|
i0.ɵɵelementEnd();
|
|
55
|
-
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_8_Conditional_7_Conditional_3_Template, 3, 0, "button", 27);
|
|
56
93
|
} if (rf & 2) {
|
|
57
94
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
58
|
-
i0.ɵɵadvance(
|
|
59
|
-
i0.ɵɵconditional(ctx_r2.
|
|
95
|
+
i0.ɵɵadvance();
|
|
96
|
+
i0.ɵɵconditional(ctx_r2.EditMode ? 1 : 2);
|
|
60
97
|
} }
|
|
61
|
-
function
|
|
62
|
-
i0.ɵɵelementStart(0, "div",
|
|
63
|
-
i0.ɵɵelement(1, "i",
|
|
98
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
99
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
100
|
+
i0.ɵɵelement(1, "i", 45);
|
|
64
101
|
i0.ɵɵelementStart(2, "span")(3, "strong");
|
|
65
102
|
i0.ɵɵtext(4, "Edit mode");
|
|
66
103
|
i0.ɵɵelementEnd();
|
|
67
104
|
i0.ɵɵtext(5, " \u2014 Drag cards to reorder. Click names to rename.");
|
|
68
105
|
i0.ɵɵelementEnd()();
|
|
69
106
|
} }
|
|
70
|
-
function
|
|
71
|
-
const
|
|
72
|
-
i0.ɵɵelementStart(0, "button",
|
|
73
|
-
i0.ɵɵlistener("click", function
|
|
74
|
-
i0.ɵɵelement(1, "i",
|
|
107
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
108
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
109
|
+
i0.ɵɵelementStart(0, "button", 51);
|
|
110
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.DismissPinEmptyState()); });
|
|
111
|
+
i0.ɵɵelement(1, "i", 52);
|
|
75
112
|
i0.ɵɵelementEnd();
|
|
76
113
|
} }
|
|
77
|
-
function
|
|
78
|
-
const
|
|
79
|
-
i0.ɵɵelementStart(0, "button",
|
|
80
|
-
i0.ɵɵlistener("click", function
|
|
114
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
115
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
116
|
+
i0.ɵɵelementStart(0, "button", 53);
|
|
117
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.DismissPinEmptyState()); });
|
|
81
118
|
i0.ɵɵtext(1, " Don't show this again ");
|
|
82
119
|
i0.ɵɵelementEnd();
|
|
83
120
|
} }
|
|
84
|
-
function
|
|
85
|
-
const
|
|
86
|
-
i0.ɵɵelementStart(0, "div",
|
|
87
|
-
i0.ɵɵconditionalCreate(1,
|
|
88
|
-
i0.ɵɵelementStart(2, "mj-empty-state",
|
|
89
|
-
i0.ɵɵlistener("click", function
|
|
90
|
-
i0.ɵɵelement(4, "i",
|
|
121
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
122
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
123
|
+
i0.ɵɵelementStart(0, "div", 43);
|
|
124
|
+
i0.ɵɵconditionalCreate(1, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Conditional_1_Template, 2, 0, "button", 46);
|
|
125
|
+
i0.ɵɵelementStart(2, "mj-empty-state", 47)(3, "button", 48);
|
|
126
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OpenAddPinPanel()); });
|
|
127
|
+
i0.ɵɵelement(4, "i", 49);
|
|
91
128
|
i0.ɵɵtext(5, " Add your first pin ");
|
|
92
129
|
i0.ɵɵelementEnd();
|
|
93
|
-
i0.ɵɵconditionalCreate(6,
|
|
130
|
+
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Conditional_6_Template, 2, 0, "button", 50);
|
|
94
131
|
i0.ɵɵelementEnd()();
|
|
95
132
|
} if (rf & 2) {
|
|
96
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
133
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
97
134
|
i0.ɵɵadvance();
|
|
98
135
|
i0.ɵɵconditional(!ctx_r2.EditMode ? 1 : -1);
|
|
99
136
|
i0.ɵɵadvance(5);
|
|
100
137
|
i0.ɵɵconditional(!ctx_r2.EditMode && !ctx_r2.HidePinEmptyState ? 6 : -1);
|
|
101
138
|
} }
|
|
102
|
-
function
|
|
103
|
-
const
|
|
104
|
-
i0.ɵɵelementStart(0, "
|
|
105
|
-
i0.ɵɵ
|
|
139
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
140
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
141
|
+
i0.ɵɵelementStart(0, "input", 62);
|
|
142
|
+
i0.ɵɵlistener("blur", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_1_Template_input_blur_0_listener($event) { i0.ɵɵrestoreView(_r10); const section_r11 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.SaveGroupName(section_r11.Group, ctx_r2.GetInputValue($event))); })("keydown.enter", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_1_Template_input_keydown_enter_0_listener($event) { i0.ɵɵrestoreView(_r10); const section_r11 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.SaveGroupName(section_r11.Group, ctx_r2.GetInputValue($event))); });
|
|
106
143
|
i0.ɵɵelementEnd();
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
i0.ɵɵ
|
|
110
|
-
i0.ɵɵelementEnd()()();
|
|
144
|
+
} if (rf & 2) {
|
|
145
|
+
const section_r11 = i0.ɵɵnextContext(2).$implicit;
|
|
146
|
+
i0.ɵɵproperty("value", section_r11.Group);
|
|
111
147
|
} }
|
|
112
|
-
function
|
|
148
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
113
149
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
114
|
-
i0.ɵɵelementStart(0, "
|
|
115
|
-
i0.ɵɵlistener("click", function
|
|
116
|
-
i0.ɵɵtext(
|
|
117
|
-
i0.ɵɵelementEnd()();
|
|
118
|
-
} }
|
|
119
|
-
function HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
120
|
-
i0.ɵɵelementStart(0, "div", 42);
|
|
121
|
-
i0.ɵɵelement(1, "img", 54);
|
|
122
|
-
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_2_Conditional_2_Template, 3, 0, "div", 55);
|
|
150
|
+
i0.ɵɵelementStart(0, "span", 63);
|
|
151
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_2_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r12); const section_r11 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.EditMode ? ctx_r2.StartEditingGroup(section_r11.Group) : null); });
|
|
152
|
+
i0.ɵɵtext(1);
|
|
123
153
|
i0.ɵɵelementEnd();
|
|
124
154
|
} if (rf & 2) {
|
|
125
|
-
const
|
|
126
|
-
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
127
|
-
i0.ɵɵadvance();
|
|
128
|
-
i0.ɵɵproperty("src", pin_r10.Thumbnail, i0.ɵɵsanitizeUrl)("alt", pin_r10.DisplayName);
|
|
155
|
+
const section_r11 = i0.ɵɵnextContext(2).$implicit;
|
|
129
156
|
i0.ɵɵadvance();
|
|
130
|
-
i0.ɵɵ
|
|
157
|
+
i0.ɵɵtextInterpolate(section_r11.Group);
|
|
131
158
|
} }
|
|
132
|
-
function
|
|
159
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
133
160
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
134
|
-
i0.ɵɵelementStart(0, "div",
|
|
135
|
-
i0.ɵɵlistener("click", function
|
|
136
|
-
i0.ɵɵ
|
|
161
|
+
i0.ɵɵelementStart(0, "div", 61)(1, "button", 64);
|
|
162
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_6_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r13); const section_r11 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.RemoveGroup(section_r11.Group)); });
|
|
163
|
+
i0.ɵɵelement(2, "i", 65);
|
|
164
|
+
i0.ɵɵtext(3, " Remove Group ");
|
|
137
165
|
i0.ɵɵelementEnd()();
|
|
138
166
|
} }
|
|
139
|
-
function
|
|
140
|
-
i0.ɵɵelementStart(0, "div",
|
|
141
|
-
i0.ɵɵ
|
|
142
|
-
i0.ɵɵ
|
|
167
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
168
|
+
i0.ɵɵelementStart(0, "div", 55);
|
|
169
|
+
i0.ɵɵconditionalCreate(1, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_1_Template, 1, 1, "input", 57)(2, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_2_Template, 2, 1, "span", 58);
|
|
170
|
+
i0.ɵɵelement(3, "div", 59);
|
|
171
|
+
i0.ɵɵelementStart(4, "span", 60);
|
|
172
|
+
i0.ɵɵtext(5);
|
|
173
|
+
i0.ɵɵelementEnd();
|
|
174
|
+
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Conditional_6_Template, 4, 0, "div", 61);
|
|
143
175
|
i0.ɵɵelementEnd();
|
|
144
176
|
} if (rf & 2) {
|
|
145
|
-
const
|
|
146
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
147
|
-
i0.ɵɵstyleProp("background", "linear-gradient(135deg, " + ctx_r2.GetPinAccentColor(pin_r10) + " 0%, " + ctx_r2.GetPinAccentColor(pin_r10) + "cc 100%)");
|
|
177
|
+
const section_r11 = i0.ɵɵnextContext().$implicit;
|
|
178
|
+
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
148
179
|
i0.ɵɵadvance();
|
|
149
|
-
i0.ɵɵ
|
|
180
|
+
i0.ɵɵconditional(ctx_r2.EditMode && ctx_r2.EditingGroupName === section_r11.Group ? 1 : 2);
|
|
181
|
+
i0.ɵɵadvance(4);
|
|
182
|
+
i0.ɵɵtextInterpolate1("", section_r11.Pins.length, " pins");
|
|
150
183
|
i0.ɵɵadvance();
|
|
151
|
-
i0.ɵɵconditional(
|
|
184
|
+
i0.ɵɵconditional(ctx_r2.EditMode ? 6 : -1);
|
|
152
185
|
} }
|
|
153
|
-
function
|
|
154
|
-
const
|
|
155
|
-
i0.ɵɵelementStart(0, "div",
|
|
156
|
-
i0.ɵɵ
|
|
186
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
187
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
188
|
+
i0.ɵɵelementStart(0, "div", 67)(1, "div", 77);
|
|
189
|
+
i0.ɵɵelement(2, "i", 78);
|
|
190
|
+
i0.ɵɵelementEnd();
|
|
191
|
+
i0.ɵɵelementStart(3, "div", 79)(4, "button", 80);
|
|
192
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_1_Template_button_click_4_listener($event) { i0.ɵɵrestoreView(_r16); const pin_r15 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); ctx_r2.RemovePin(pin_r15.Id); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
193
|
+
i0.ɵɵelement(5, "i", 81);
|
|
194
|
+
i0.ɵɵelementEnd()()();
|
|
195
|
+
} }
|
|
196
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
197
|
+
const _r17 = i0.ɵɵgetCurrentView();
|
|
198
|
+
i0.ɵɵelementStart(0, "div", 83)(1, "button", 39);
|
|
199
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_2_Conditional_2_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r17); const pin_r15 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); ctx_r2.OnPinClick(pin_r15); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
157
200
|
i0.ɵɵtext(2, "Open");
|
|
158
201
|
i0.ɵɵelementEnd()();
|
|
202
|
+
} if (rf & 2) {
|
|
203
|
+
const pin_r15 = i0.ɵɵnextContext(2).$implicit;
|
|
204
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
205
|
+
i0.ɵɵadvance();
|
|
206
|
+
i0.ɵɵattribute("aria-label", "Open " + ctx_r2.PinName(pin_r15));
|
|
159
207
|
} }
|
|
160
|
-
function
|
|
161
|
-
i0.ɵɵelementStart(0, "div",
|
|
162
|
-
i0.ɵɵelement(1, "
|
|
163
|
-
i0.ɵɵconditionalCreate(2,
|
|
208
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
209
|
+
i0.ɵɵelementStart(0, "div", 68);
|
|
210
|
+
i0.ɵɵelement(1, "img", 82);
|
|
211
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_2_Conditional_2_Template, 3, 1, "div", 83);
|
|
164
212
|
i0.ɵɵelementEnd();
|
|
165
213
|
} if (rf & 2) {
|
|
166
|
-
const
|
|
167
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
168
|
-
i0.ɵɵstyleProp("--pin-icon-color", pin_r10.Color || "var(--mj-text-muted)");
|
|
214
|
+
const pin_r15 = i0.ɵɵnextContext().$implicit;
|
|
215
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
169
216
|
i0.ɵɵadvance();
|
|
170
|
-
i0.ɵɵ
|
|
217
|
+
i0.ɵɵproperty("src", pin_r15.Thumbnail, i0.ɵɵsanitizeUrl)("alt", ctx_r2.PinName(pin_r15));
|
|
171
218
|
i0.ɵɵadvance();
|
|
172
219
|
i0.ɵɵconditional(!ctx_r2.EditMode ? 2 : -1);
|
|
173
220
|
} }
|
|
174
|
-
function
|
|
175
|
-
const
|
|
176
|
-
i0.ɵɵelementStart(0, "
|
|
177
|
-
i0.ɵɵlistener("
|
|
178
|
-
i0.ɵɵ
|
|
221
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
222
|
+
const _r18 = i0.ɵɵgetCurrentView();
|
|
223
|
+
i0.ɵɵelementStart(0, "div", 83)(1, "button", 39);
|
|
224
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_3_Conditional_2_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r18); const pin_r15 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); ctx_r2.OnPinClick(pin_r15); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
225
|
+
i0.ɵɵtext(2, "Run");
|
|
226
|
+
i0.ɵɵelementEnd()();
|
|
179
227
|
} if (rf & 2) {
|
|
180
|
-
const
|
|
181
|
-
i0.ɵɵ
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const _r17 = i0.ɵɵgetCurrentView();
|
|
185
|
-
i0.ɵɵelementStart(0, "button", 62);
|
|
186
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_7_Conditional_2_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r17); const pin_r10 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.ShowPinMenu($event, pin_r10)); });
|
|
187
|
-
i0.ɵɵelement(1, "i", 63);
|
|
188
|
-
i0.ɵɵelementEnd();
|
|
228
|
+
const pin_r15 = i0.ɵɵnextContext(2).$implicit;
|
|
229
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
230
|
+
i0.ɵɵadvance();
|
|
231
|
+
i0.ɵɵattribute("aria-label", "Run " + ctx_r2.PinName(pin_r15));
|
|
189
232
|
} }
|
|
190
|
-
function
|
|
191
|
-
|
|
192
|
-
i0.ɵɵ
|
|
193
|
-
i0.ɵɵ
|
|
194
|
-
i0.ɵɵtext(1);
|
|
195
|
-
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_7_Conditional_2_Template, 2, 0, "button", 61);
|
|
233
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
234
|
+
i0.ɵɵelementStart(0, "div", 84);
|
|
235
|
+
i0.ɵɵelement(1, "i", 85);
|
|
236
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_3_Conditional_2_Template, 3, 1, "div", 83);
|
|
196
237
|
i0.ɵɵelementEnd();
|
|
197
238
|
} if (rf & 2) {
|
|
198
|
-
const
|
|
199
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
239
|
+
const pin_r15 = i0.ɵɵnextContext().$implicit;
|
|
240
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
241
|
+
i0.ɵɵstyleProp("background", "linear-gradient(135deg, " + ctx_r2.GetPinAccentColor(pin_r15) + " 0%, " + ctx_r2.GetPinAccentColor(pin_r15) + "cc 100%)");
|
|
200
242
|
i0.ɵɵadvance();
|
|
201
|
-
i0.ɵɵ
|
|
243
|
+
i0.ɵɵclassMap(ctx_r2.GetPinIcon(pin_r15));
|
|
202
244
|
i0.ɵɵadvance();
|
|
203
245
|
i0.ɵɵconditional(!ctx_r2.EditMode ? 2 : -1);
|
|
204
246
|
} }
|
|
205
|
-
function
|
|
206
|
-
i0.ɵɵ
|
|
207
|
-
i0.ɵɵ
|
|
208
|
-
i0.ɵɵ
|
|
247
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_4_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
248
|
+
const _r19 = i0.ɵɵgetCurrentView();
|
|
249
|
+
i0.ɵɵelementStart(0, "div", 83)(1, "button", 39);
|
|
250
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_4_Conditional_2_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r19); const pin_r15 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); ctx_r2.OnPinClick(pin_r15); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
251
|
+
i0.ɵɵtext(2, "Open");
|
|
252
|
+
i0.ɵɵelementEnd()();
|
|
209
253
|
} if (rf & 2) {
|
|
210
|
-
const
|
|
254
|
+
const pin_r15 = i0.ɵɵnextContext(2).$implicit;
|
|
255
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
211
256
|
i0.ɵɵadvance();
|
|
212
|
-
i0.ɵɵ
|
|
257
|
+
i0.ɵɵattribute("aria-label", "Open " + ctx_r2.PinName(pin_r15));
|
|
213
258
|
} }
|
|
214
|
-
function
|
|
215
|
-
|
|
216
|
-
i0.ɵɵ
|
|
217
|
-
i0.ɵɵ
|
|
218
|
-
i0.ɵɵ
|
|
219
|
-
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_2_Template, 3, 3, "div", 42)(3, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_3_Template, 3, 5, "div", 43)(4, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_4_Template, 3, 5, "div", 44);
|
|
220
|
-
i0.ɵɵelementStart(5, "div", 45);
|
|
221
|
-
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_6_Template, 1, 1, "input", 46)(7, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_7_Template, 3, 2, "div", 47);
|
|
222
|
-
i0.ɵɵelementStart(8, "div", 48);
|
|
223
|
-
i0.ɵɵelement(9, "i");
|
|
224
|
-
i0.ɵɵtext(10);
|
|
225
|
-
i0.ɵɵconditionalCreate(11, HomeDashboardComponent_Conditional_8_Conditional_10_For_2_Conditional_11_Template, 2, 1, "span", 49);
|
|
226
|
-
i0.ɵɵelementEnd()()();
|
|
259
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
260
|
+
i0.ɵɵelementStart(0, "div", 70);
|
|
261
|
+
i0.ɵɵelement(1, "i", 85);
|
|
262
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_4_Conditional_2_Template, 3, 1, "div", 83);
|
|
263
|
+
i0.ɵɵelementEnd();
|
|
227
264
|
} if (rf & 2) {
|
|
228
|
-
const
|
|
229
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
230
|
-
i0.ɵɵclassProp("edit-mode", ctx_r2.EditMode)("dragging", ctx_r2.DraggingPinId === pin_r10.Id)("drag-over", ctx_r2.DragOverPinId === pin_r10.Id);
|
|
231
|
-
i0.ɵɵproperty("draggable", ctx_r2.EditMode);
|
|
265
|
+
const pin_r15 = i0.ɵɵnextContext().$implicit;
|
|
266
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
232
267
|
i0.ɵɵadvance();
|
|
233
|
-
i0.ɵɵ
|
|
268
|
+
i0.ɵɵclassMap(ctx_r2.GetPinIcon(pin_r15));
|
|
234
269
|
i0.ɵɵadvance();
|
|
235
|
-
i0.ɵɵconditional(
|
|
236
|
-
i0.ɵɵadvance(4);
|
|
237
|
-
i0.ɵɵconditional(ctx_r2.EditMode && ctx_r2.EditingPinId === pin_r10.Id ? 6 : 7);
|
|
238
|
-
i0.ɵɵadvance(3);
|
|
239
|
-
i0.ɵɵclassMap(ctx_r2.GetPinIcon(pin_r10));
|
|
240
|
-
i0.ɵɵadvance();
|
|
241
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r2.GetResourceTypeLabel(pin_r10), " ");
|
|
242
|
-
i0.ɵɵadvance();
|
|
243
|
-
i0.ɵɵconditional(pin_r10.ApplicationName && pin_r10.ResourceType !== "Custom" ? 11 : -1);
|
|
270
|
+
i0.ɵɵconditional(!ctx_r2.EditMode ? 2 : -1);
|
|
244
271
|
} }
|
|
245
|
-
function
|
|
246
|
-
const
|
|
247
|
-
i0.ɵɵelementStart(0, "input",
|
|
248
|
-
i0.ɵɵlistener("blur", function
|
|
272
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
273
|
+
const _r20 = i0.ɵɵgetCurrentView();
|
|
274
|
+
i0.ɵɵelementStart(0, "input", 86);
|
|
275
|
+
i0.ɵɵlistener("blur", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_6_Template_input_blur_0_listener($event) { i0.ɵɵrestoreView(_r20); const pin_r15 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.SavePinName(pin_r15.Id, ctx_r2.GetInputValue($event))); })("keydown.enter", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_6_Template_input_keydown_enter_0_listener($event) { i0.ɵɵrestoreView(_r20); const pin_r15 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnPinNameEnter(pin_r15.Id, $event)); })("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_6_Template_input_click_0_listener($event) { return $event.stopPropagation(); });
|
|
249
276
|
i0.ɵɵelementEnd();
|
|
250
277
|
} if (rf & 2) {
|
|
251
|
-
const
|
|
252
|
-
i0.ɵɵ
|
|
278
|
+
const pin_r15 = i0.ɵɵnextContext().$implicit;
|
|
279
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
280
|
+
i0.ɵɵproperty("value", ctx_r2.PinName(pin_r15));
|
|
281
|
+
i0.ɵɵattribute("aria-label", "Name of " + ctx_r2.PinName(pin_r15));
|
|
253
282
|
} }
|
|
254
|
-
function
|
|
255
|
-
const
|
|
256
|
-
i0.ɵɵelementStart(0, "
|
|
257
|
-
i0.ɵɵlistener("click", function
|
|
258
|
-
i0.ɵɵ
|
|
283
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_7_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
284
|
+
const _r22 = i0.ɵɵgetCurrentView();
|
|
285
|
+
i0.ɵɵelementStart(0, "button", 90);
|
|
286
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_7_Conditional_3_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r22); const pin_r15 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.ShowPinMenu($event, pin_r15)); });
|
|
287
|
+
i0.ɵɵelement(1, "i", 91);
|
|
259
288
|
i0.ɵɵelementEnd();
|
|
260
289
|
} if (rf & 2) {
|
|
261
|
-
const
|
|
262
|
-
i0.ɵɵ
|
|
263
|
-
i0.ɵɵ
|
|
290
|
+
const pin_r15 = i0.ɵɵnextContext(2).$implicit;
|
|
291
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
292
|
+
i0.ɵɵattribute("aria-label", "Pin options for " + ctx_r2.PinName(pin_r15))("aria-expanded", (ctx_r2.PinMenuPin == null ? null : ctx_r2.PinMenuPin.Id) === pin_r15.Id);
|
|
264
293
|
} }
|
|
265
|
-
function
|
|
294
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
266
295
|
const _r21 = i0.ɵɵgetCurrentView();
|
|
267
|
-
i0.ɵɵelementStart(0, "div",
|
|
268
|
-
i0.ɵɵlistener("click", function
|
|
269
|
-
i0.ɵɵ
|
|
270
|
-
i0.ɵɵtext(
|
|
271
|
-
i0.ɵɵelementEnd()();
|
|
272
|
-
} }
|
|
273
|
-
function HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
274
|
-
const _r24 = i0.ɵɵgetCurrentView();
|
|
275
|
-
i0.ɵɵelementStart(0, "div", 41)(1, "div", 50);
|
|
276
|
-
i0.ɵɵelement(2, "i", 51);
|
|
296
|
+
i0.ɵɵelementStart(0, "div", 87);
|
|
297
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_7_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r21); const pin_r15 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.EditMode ? ctx_r2.StartEditingPin(pin_r15.Id, $event) : null); });
|
|
298
|
+
i0.ɵɵelementStart(1, "span", 88);
|
|
299
|
+
i0.ɵɵtext(2);
|
|
277
300
|
i0.ɵɵelementEnd();
|
|
278
|
-
i0.ɵɵ
|
|
279
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_1_Template_button_click_4_listener($event) { i0.ɵɵrestoreView(_r24); const pin_r23 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.RemovePin(pin_r23.Id); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
280
|
-
i0.ɵɵelement(5, "i", 36);
|
|
281
|
-
i0.ɵɵelementEnd()()();
|
|
282
|
-
} }
|
|
283
|
-
function HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
284
|
-
const _r25 = i0.ɵɵgetCurrentView();
|
|
285
|
-
i0.ɵɵelementStart(0, "div", 55)(1, "button", 56);
|
|
286
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_2_Conditional_2_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r25); const pin_r23 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.OnPinClick(pin_r23); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
287
|
-
i0.ɵɵtext(2, "Open");
|
|
288
|
-
i0.ɵɵelementEnd()();
|
|
289
|
-
} }
|
|
290
|
-
function HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
291
|
-
i0.ɵɵelementStart(0, "div", 42);
|
|
292
|
-
i0.ɵɵelement(1, "img", 54);
|
|
293
|
-
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_2_Conditional_2_Template, 3, 0, "div", 55);
|
|
301
|
+
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_7_Conditional_3_Template, 2, 2, "button", 89);
|
|
294
302
|
i0.ɵɵelementEnd();
|
|
295
303
|
} if (rf & 2) {
|
|
296
|
-
const
|
|
297
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
298
|
-
i0.ɵɵadvance();
|
|
299
|
-
i0.ɵɵ
|
|
304
|
+
const pin_r15 = i0.ɵɵnextContext().$implicit;
|
|
305
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
306
|
+
i0.ɵɵadvance(2);
|
|
307
|
+
i0.ɵɵtextInterpolate(ctx_r2.PinName(pin_r15));
|
|
300
308
|
i0.ɵɵadvance();
|
|
301
|
-
i0.ɵɵconditional(!ctx_r2.EditMode ?
|
|
309
|
+
i0.ɵɵconditional(!ctx_r2.EditMode ? 3 : -1);
|
|
302
310
|
} }
|
|
303
|
-
function
|
|
304
|
-
|
|
305
|
-
i0.ɵɵelementStart(0, "div", 55)(1, "button", 56);
|
|
306
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_3_Conditional_2_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r26); const pin_r23 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.OnPinClick(pin_r23); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
307
|
-
i0.ɵɵtext(2, "Run");
|
|
308
|
-
i0.ɵɵelementEnd()();
|
|
311
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
312
|
+
i0.ɵɵelement(0, "i", 75);
|
|
309
313
|
} }
|
|
310
|
-
function
|
|
311
|
-
i0.ɵɵ
|
|
312
|
-
i0.ɵɵ
|
|
313
|
-
i0.ɵɵ
|
|
314
|
-
i0.ɵɵ
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
i0.ɵɵ
|
|
314
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
315
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
316
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
317
|
+
i0.ɵɵlistener("dragstart", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template_div_dragstart_0_listener($event) { const pin_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnDragStart($event, pin_r15)); })("dragover", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template_div_dragover_0_listener($event) { const pin_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnDragOver($event, pin_r15)); })("dragleave", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template_div_dragleave_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnDragLeave()); })("drop", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template_div_drop_0_listener($event) { const pin_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnDrop($event, pin_r15)); })("dragend", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template_div_dragend_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnDragEnd()); })("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template_div_click_0_listener() { const pin_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OnPinClick(pin_r15)); });
|
|
318
|
+
i0.ɵɵconditionalCreate(1, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_1_Template, 6, 0, "div", 67);
|
|
319
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_2_Template, 3, 3, "div", 68)(3, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_3_Template, 3, 5, "div", 69)(4, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_4_Template, 3, 3, "div", 70);
|
|
320
|
+
i0.ɵɵelementStart(5, "div", 71);
|
|
321
|
+
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_6_Template, 1, 2, "input", 72)(7, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_7_Template, 4, 2, "div", 73);
|
|
322
|
+
i0.ɵɵelementStart(8, "div", 74);
|
|
323
|
+
i0.ɵɵconditionalCreate(9, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Conditional_9_Template, 1, 0, "i", 75);
|
|
324
|
+
i0.ɵɵelementStart(10, "span", 76);
|
|
325
|
+
i0.ɵɵtext(11);
|
|
326
|
+
i0.ɵɵelementEnd()()()();
|
|
327
|
+
} if (rf & 2) {
|
|
328
|
+
const pin_r15 = ctx.$implicit;
|
|
329
|
+
const ctx_r2 = i0.ɵɵnextContext(5);
|
|
330
|
+
i0.ɵɵclassProp("edit-mode", ctx_r2.EditMode)("dragging", ctx_r2.DraggingPinId === pin_r15.Id)("drag-over", ctx_r2.DragOverPinId === pin_r15.Id)("menu-open", (ctx_r2.PinMenuPin == null ? null : ctx_r2.PinMenuPin.Id) === pin_r15.Id);
|
|
331
|
+
i0.ɵɵproperty("draggable", ctx_r2.EditMode);
|
|
319
332
|
i0.ɵɵadvance();
|
|
320
|
-
i0.ɵɵ
|
|
333
|
+
i0.ɵɵconditional(ctx_r2.EditMode ? 1 : -1);
|
|
321
334
|
i0.ɵɵadvance();
|
|
322
|
-
i0.ɵɵconditional(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
i0.ɵɵ
|
|
327
|
-
i0.ɵɵ
|
|
328
|
-
i0.ɵɵ
|
|
329
|
-
i0.ɵɵelementEnd()();
|
|
335
|
+
i0.ɵɵconditional(pin_r15.Thumbnail ? 2 : pin_r15.ResourceType === "Actions" ? 3 : 4);
|
|
336
|
+
i0.ɵɵadvance(4);
|
|
337
|
+
i0.ɵɵconditional(ctx_r2.EditMode && ctx_r2.EditingPinId === pin_r15.Id ? 6 : 7);
|
|
338
|
+
i0.ɵɵadvance(3);
|
|
339
|
+
i0.ɵɵconditional(pin_r15.ResourceType === "Dashboards" ? 9 : -1);
|
|
340
|
+
i0.ɵɵadvance(2);
|
|
341
|
+
i0.ɵɵtextInterpolate(ctx_r2.GetResourceTypeLabel(pin_r15));
|
|
330
342
|
} }
|
|
331
|
-
function
|
|
332
|
-
i0.ɵɵ
|
|
333
|
-
i0.ɵɵ
|
|
334
|
-
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_4_Conditional_2_Template, 3, 0, "div", 55);
|
|
335
|
-
i0.ɵɵelementEnd();
|
|
343
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
344
|
+
i0.ɵɵconditionalCreate(0, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Conditional_0_Template, 7, 3, "div", 55);
|
|
345
|
+
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_For_2_Template, 12, 14, "div", 56, _forTrack1);
|
|
336
346
|
} if (rf & 2) {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
i0.ɵɵstyleProp("--pin-icon-color", pin_r23.Color || "var(--mj-text-muted)");
|
|
347
|
+
const section_r11 = ctx.$implicit;
|
|
348
|
+
i0.ɵɵconditional(section_r11.Group !== null ? 0 : -1);
|
|
340
349
|
i0.ɵɵadvance();
|
|
341
|
-
i0.ɵɵ
|
|
342
|
-
i0.ɵɵadvance();
|
|
343
|
-
i0.ɵɵconditional(!ctx_r2.EditMode ? 2 : -1);
|
|
350
|
+
i0.ɵɵrepeater(section_r11.Pins);
|
|
344
351
|
} }
|
|
345
|
-
function
|
|
346
|
-
const
|
|
347
|
-
i0.ɵɵelementStart(0, "
|
|
348
|
-
i0.ɵɵlistener("
|
|
349
|
-
i0.ɵɵ
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
i0.ɵɵ
|
|
352
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
353
|
+
const _r23 = i0.ɵɵgetCurrentView();
|
|
354
|
+
i0.ɵɵelementStart(0, "div", 92);
|
|
355
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_Conditional_3_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.OpenAddPinPanel()); });
|
|
356
|
+
i0.ɵɵelement(1, "i", 36);
|
|
357
|
+
i0.ɵɵelementStart(2, "span");
|
|
358
|
+
i0.ɵɵtext(3, "Add Pin");
|
|
359
|
+
i0.ɵɵelementEnd()();
|
|
353
360
|
} }
|
|
354
|
-
function
|
|
355
|
-
i0.ɵɵelementStart(0, "
|
|
356
|
-
i0.ɵɵ
|
|
357
|
-
i0.ɵɵ
|
|
361
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
362
|
+
i0.ɵɵelementStart(0, "div", 44);
|
|
363
|
+
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_For_2_Template, 3, 1, null, null, _forTrack0);
|
|
364
|
+
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_Conditional_3_Template, 4, 0, "div", 54);
|
|
358
365
|
i0.ɵɵelementEnd();
|
|
366
|
+
} if (rf & 2) {
|
|
367
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
368
|
+
i0.ɵɵadvance();
|
|
369
|
+
i0.ɵɵrepeater(ctx_r2.PinSections);
|
|
370
|
+
i0.ɵɵadvance(2);
|
|
371
|
+
i0.ɵɵconditional(ctx_r2.EditMode ? 3 : -1);
|
|
359
372
|
} }
|
|
360
|
-
function
|
|
361
|
-
|
|
362
|
-
i0.ɵɵ
|
|
363
|
-
i0.ɵɵ
|
|
364
|
-
i0.ɵɵ
|
|
365
|
-
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_8_Conditional_10_For_4_For_8_Conditional_7_Conditional_2_Template, 2, 0, "button", 61);
|
|
373
|
+
function HomeDashboardComponent_Conditional_2_ng_template_10_Template(rf, ctx) { if (rf & 1) {
|
|
374
|
+
i0.ɵɵelementStart(0, "div", 41);
|
|
375
|
+
i0.ɵɵconditionalCreate(1, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_1_Template, 6, 0, "div", 42);
|
|
376
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_2_Template, 7, 2, "div", 43);
|
|
377
|
+
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_2_ng_template_10_Conditional_3_Template, 4, 1, "div", 44);
|
|
366
378
|
i0.ɵɵelementEnd();
|
|
367
379
|
} if (rf & 2) {
|
|
368
|
-
const
|
|
369
|
-
|
|
380
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
381
|
+
i0.ɵɵadvance();
|
|
382
|
+
i0.ɵɵconditional(ctx_r2.EditMode ? 1 : -1);
|
|
370
383
|
i0.ɵɵadvance();
|
|
371
|
-
i0.ɵɵ
|
|
384
|
+
i0.ɵɵconditional(ctx_r2.PinnedItems.length === 0 && (ctx_r2.EditMode || !ctx_r2.HidePinEmptyState) ? 2 : -1);
|
|
372
385
|
i0.ɵɵadvance();
|
|
373
|
-
i0.ɵɵconditional(
|
|
386
|
+
i0.ɵɵconditional(ctx_r2.PinnedItems.length > 0 ? 3 : -1);
|
|
374
387
|
} }
|
|
375
|
-
function
|
|
376
|
-
i0.ɵɵelementStart(0, "
|
|
388
|
+
function HomeDashboardComponent_Conditional_2_For_16_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
389
|
+
i0.ɵɵelementStart(0, "p", 97);
|
|
377
390
|
i0.ɵɵtext(1);
|
|
378
391
|
i0.ɵɵelementEnd();
|
|
379
392
|
} if (rf & 2) {
|
|
380
|
-
const
|
|
393
|
+
const appData_r25 = i0.ɵɵnextContext().$implicit;
|
|
381
394
|
i0.ɵɵadvance();
|
|
382
|
-
i0.ɵɵtextInterpolate(
|
|
395
|
+
i0.ɵɵtextInterpolate(appData_r25.app.Description);
|
|
383
396
|
} }
|
|
384
|
-
function
|
|
385
|
-
const
|
|
386
|
-
i0.ɵɵelementStart(0, "div",
|
|
387
|
-
i0.ɵɵlistener("
|
|
388
|
-
i0.ɵɵ
|
|
389
|
-
i0.ɵɵ
|
|
390
|
-
i0.ɵɵ
|
|
391
|
-
i0.ɵɵ
|
|
392
|
-
i0.ɵɵ
|
|
393
|
-
i0.ɵɵ
|
|
394
|
-
i0.ɵɵ
|
|
395
|
-
i0.ɵɵ
|
|
396
|
-
i0.ɵɵelementEnd()()();
|
|
397
|
+
function HomeDashboardComponent_Conditional_2_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
398
|
+
const _r24 = i0.ɵɵgetCurrentView();
|
|
399
|
+
i0.ɵɵelementStart(0, "div", 93);
|
|
400
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_2_For_16_Template_div_click_0_listener() { const appData_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnAppClick(appData_r25.app)); });
|
|
401
|
+
i0.ɵɵelementStart(1, "div", 94);
|
|
402
|
+
i0.ɵɵelement(2, "i");
|
|
403
|
+
i0.ɵɵelementEnd();
|
|
404
|
+
i0.ɵɵelementStart(3, "div", 95)(4, "h3", 96);
|
|
405
|
+
i0.ɵɵtext(5);
|
|
406
|
+
i0.ɵɵelementEnd();
|
|
407
|
+
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_2_For_16_Conditional_6_Template, 2, 1, "p", 97);
|
|
408
|
+
i0.ɵɵelementEnd()();
|
|
397
409
|
} if (rf & 2) {
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
i0.ɵɵ
|
|
401
|
-
i0.ɵɵ
|
|
402
|
-
i0.ɵɵ
|
|
403
|
-
i0.ɵɵconditional(ctx_r2.EditMode ? 1 : -1);
|
|
404
|
-
i0.ɵɵadvance();
|
|
405
|
-
i0.ɵɵconditional(pin_r23.Thumbnail ? 2 : pin_r23.ResourceType === "Actions" ? 3 : 4);
|
|
406
|
-
i0.ɵɵadvance(4);
|
|
407
|
-
i0.ɵɵconditional(ctx_r2.EditMode && ctx_r2.EditingPinId === pin_r23.Id ? 6 : 7);
|
|
410
|
+
const appData_r25 = ctx.$implicit;
|
|
411
|
+
i0.ɵɵstyleProp("--app-color", appData_r25.color);
|
|
412
|
+
i0.ɵɵproperty("mjClickable", appData_r25.app.Name)("TestId", "app-tile-" + appData_r25.app.Name);
|
|
413
|
+
i0.ɵɵadvance(2);
|
|
414
|
+
i0.ɵɵclassMap(appData_r25.icon);
|
|
408
415
|
i0.ɵɵadvance(3);
|
|
409
|
-
i0.ɵɵ
|
|
410
|
-
i0.ɵɵadvance();
|
|
411
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r2.GetResourceTypeLabel(pin_r23), " ");
|
|
416
|
+
i0.ɵɵtextInterpolate(appData_r25.app.Name);
|
|
412
417
|
i0.ɵɵadvance();
|
|
413
|
-
i0.ɵɵconditional(
|
|
418
|
+
i0.ɵɵconditional(appData_r25.app.Description ? 6 : -1);
|
|
414
419
|
} }
|
|
415
|
-
function
|
|
416
|
-
i0.ɵɵ
|
|
417
|
-
i0.ɵɵ
|
|
418
|
-
i0.ɵɵ
|
|
419
|
-
i0.ɵɵ
|
|
420
|
-
|
|
420
|
+
function HomeDashboardComponent_Conditional_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
421
|
+
const _r26 = i0.ɵɵgetCurrentView();
|
|
422
|
+
i0.ɵɵelementStart(0, "mj-empty-state", 98);
|
|
423
|
+
i0.ɵɵlistener("Action", function HomeDashboardComponent_Conditional_2_Conditional_17_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r26); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OpenConfigDialog()); });
|
|
424
|
+
i0.ɵɵelementEnd();
|
|
425
|
+
} }
|
|
426
|
+
function HomeDashboardComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
427
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
428
|
+
i0.ɵɵelementStart(0, "div", 6)(1, "div", 16)(2, "div", 17)(3, "h1");
|
|
429
|
+
i0.ɵɵtext(4);
|
|
430
|
+
i0.ɵɵelementEnd();
|
|
431
|
+
i0.ɵɵelementStart(5, "p", 18);
|
|
432
|
+
i0.ɵɵtext(6);
|
|
433
|
+
i0.ɵɵelementEnd()()();
|
|
434
|
+
i0.ɵɵelementStart(7, "mj-accordion-panel", 19);
|
|
435
|
+
i0.ɵɵlistener("ExpandedChange", function HomeDashboardComponent_Conditional_2_Template_mj_accordion_panel_ExpandedChange_7_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnPinnedExpandedChange($event)); });
|
|
436
|
+
i0.ɵɵtemplate(8, HomeDashboardComponent_Conditional_2_ng_template_8_Template, 3, 0, "ng-template", 20)(9, HomeDashboardComponent_Conditional_2_ng_template_9_Template, 3, 1, "ng-template", 21)(10, HomeDashboardComponent_Conditional_2_ng_template_10_Template, 4, 3, "ng-template", 22);
|
|
421
437
|
i0.ɵɵelementEnd();
|
|
422
|
-
i0.ɵɵ
|
|
438
|
+
i0.ɵɵelementStart(11, "section", 23)(12, "h2", 24);
|
|
439
|
+
i0.ɵɵtext(13, "My applications");
|
|
423
440
|
i0.ɵɵelementEnd();
|
|
424
|
-
i0.ɵɵ
|
|
441
|
+
i0.ɵɵelementStart(14, "div", 25);
|
|
442
|
+
i0.ɵɵrepeaterCreate(15, HomeDashboardComponent_Conditional_2_For_16_Template, 7, 8, "div", 26, i0.ɵɵcomponentInstance().TrackByApp, true);
|
|
443
|
+
i0.ɵɵelementEnd();
|
|
444
|
+
i0.ɵɵconditionalCreate(17, HomeDashboardComponent_Conditional_2_Conditional_17_Template, 1, 0, "mj-empty-state", 27);
|
|
445
|
+
i0.ɵɵelementEnd()();
|
|
425
446
|
} if (rf & 2) {
|
|
426
|
-
const
|
|
427
|
-
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
428
|
-
i0.ɵɵadvance();
|
|
429
|
-
i0.ɵɵconditional(ctx_r2.EditMode && ctx_r2.EditingGroupName === group_r19 ? 1 : 2);
|
|
447
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
430
448
|
i0.ɵɵadvance(4);
|
|
431
|
-
i0.ɵɵ
|
|
432
|
-
i0.ɵɵadvance();
|
|
433
|
-
i0.ɵɵ
|
|
449
|
+
i0.ɵɵtextInterpolate2("", ctx_r2.Greeting, ", ", ctx_r2.GreetingName);
|
|
450
|
+
i0.ɵɵadvance(2);
|
|
451
|
+
i0.ɵɵtextInterpolate(ctx_r2.FormattedDate);
|
|
434
452
|
i0.ɵɵadvance();
|
|
435
|
-
i0.ɵɵ
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
i0.ɵɵ
|
|
440
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_8_Conditional_10_Conditional_5_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r30); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OpenAddPinPanel()); });
|
|
441
|
-
i0.ɵɵelement(1, "i", 26);
|
|
442
|
-
i0.ɵɵelementStart(2, "span");
|
|
443
|
-
i0.ɵɵtext(3, "Add Pin");
|
|
444
|
-
i0.ɵɵelementEnd()();
|
|
453
|
+
i0.ɵɵproperty("Bare", true)("TitleIconMuted", true)("HeadingLevel", 2)("FlushBody", true)("Expanded", ctx_r2.PinnedExpanded);
|
|
454
|
+
i0.ɵɵadvance(8);
|
|
455
|
+
i0.ɵɵrepeater(ctx_r2.AppsDisplayData);
|
|
456
|
+
i0.ɵɵadvance(2);
|
|
457
|
+
i0.ɵɵconditional(ctx_r2.Apps.length === 0 ? 17 : -1);
|
|
445
458
|
} }
|
|
446
|
-
function
|
|
447
|
-
i0.ɵɵ
|
|
448
|
-
i0.ɵɵ
|
|
449
|
-
i0.ɵɵ
|
|
450
|
-
i0.ɵɵ
|
|
459
|
+
function HomeDashboardComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
460
|
+
const _r27 = i0.ɵɵgetCurrentView();
|
|
461
|
+
i0.ɵɵelementStart(0, "mj-dashboard-editor", 99, 2);
|
|
462
|
+
i0.ɵɵtwoWayListener("StartInEditModeChange", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_StartInEditModeChange_0_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.DashboardStartsInEditMode, $event) || (ctx_r2.DashboardStartsInEditMode = $event); return i0.ɵɵresetView($event); });
|
|
463
|
+
i0.ɵɵlistener("Loaded", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_Loaded_0_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnDashboardViewLoaded($event)); })("EditingChange", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_EditingChange_0_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnDashboardEditingChange($event)); })("NameChanged", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_NameChanged_0_listener() { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnDashboardSaved()); })("Saved", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_Saved_0_listener() { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnDashboardSaved()); })("LoadFailed", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_LoadFailed_0_listener() { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnDashboardViewLoadFailed()); })("OpenInDashboardsRequested", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_OpenInDashboardsRequested_0_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OpenDashboardInDashboardsApp($event)); })("NavigationRequested", function HomeDashboardComponent_Conditional_3_Template_mj_dashboard_editor_NavigationRequested_0_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnDashboardNavigationRequested($event)); });
|
|
451
464
|
i0.ɵɵelementEnd();
|
|
452
465
|
} if (rf & 2) {
|
|
453
|
-
const ctx_r2 = i0.ɵɵnextContext(
|
|
454
|
-
i0.ɵɵ
|
|
455
|
-
i0.ɵɵ
|
|
456
|
-
i0.ɵɵ
|
|
457
|
-
i0.ɵɵ
|
|
458
|
-
i0.ɵɵadvance(2);
|
|
459
|
-
i0.ɵɵconditional(ctx_r2.EditMode ? 5 : -1);
|
|
466
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
467
|
+
const homeDashboardTitle_r28 = i0.ɵɵreference(5);
|
|
468
|
+
i0.ɵɵproperty("Provider", ctx_r2.Provider)("DashboardId", ctx_r2.CurrentDashboardId);
|
|
469
|
+
i0.ɵɵtwoWayProperty("StartInEditMode", ctx_r2.DashboardStartsInEditMode);
|
|
470
|
+
i0.ɵɵproperty("TitleTemplate", homeDashboardTitle_r28)("ShowOpenInDashboards", true);
|
|
460
471
|
} }
|
|
461
|
-
function
|
|
462
|
-
|
|
463
|
-
i0.ɵɵ
|
|
464
|
-
i0.ɵɵ
|
|
472
|
+
function HomeDashboardComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) {
|
|
473
|
+
const _r29 = i0.ɵɵgetCurrentView();
|
|
474
|
+
i0.ɵɵelementStart(0, "div", 100)(1, "nav", 101)(2, "button", 102);
|
|
475
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_ng_template_4_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r29); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnSwitcherPick(null)); });
|
|
476
|
+
i0.ɵɵelement(3, "i", 103);
|
|
477
|
+
i0.ɵɵtext(4, " Home");
|
|
465
478
|
i0.ɵɵelementEnd();
|
|
466
|
-
i0.ɵɵelementStart(5, "
|
|
467
|
-
i0.ɵɵ
|
|
468
|
-
i0.ɵɵelementEnd()();
|
|
469
|
-
i0.ɵɵconditionalCreate(8, HomeDashboardComponent_Conditional_8_Conditional_8_Template, 6, 0, "div", 20);
|
|
470
|
-
i0.ɵɵconditionalCreate(9, HomeDashboardComponent_Conditional_8_Conditional_9_Template, 7, 2, "div", 21);
|
|
471
|
-
i0.ɵɵconditionalCreate(10, HomeDashboardComponent_Conditional_8_Conditional_10_Template, 6, 1, "div", 22);
|
|
479
|
+
i0.ɵɵelementStart(5, "span", 85);
|
|
480
|
+
i0.ɵɵtext(6, "/");
|
|
472
481
|
i0.ɵɵelementEnd();
|
|
482
|
+
i0.ɵɵelementStart(7, "span");
|
|
483
|
+
i0.ɵɵtext(8, "Pinned dashboards");
|
|
484
|
+
i0.ɵɵelementEnd()();
|
|
485
|
+
i0.ɵɵelementStart(9, "mj-home-dashboard-switcher", 104);
|
|
486
|
+
i0.ɵɵlistener("Pick", function HomeDashboardComponent_ng_template_4_Template_mj_home_dashboard_switcher_Pick_9_listener($event) { i0.ɵɵrestoreView(_r29); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnSwitcherPick($event)); })("New", function HomeDashboardComponent_ng_template_4_Template_mj_home_dashboard_switcher_New_9_listener() { i0.ɵɵrestoreView(_r29); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OpenNewDashboardDialog()); })("ManagePins", function HomeDashboardComponent_ng_template_4_Template_mj_home_dashboard_switcher_ManagePins_9_listener() { i0.ɵɵrestoreView(_r29); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ManagePins()); });
|
|
487
|
+
i0.ɵɵelementEnd()();
|
|
473
488
|
} if (rf & 2) {
|
|
489
|
+
const dashboard_r30 = ctx.$implicit;
|
|
474
490
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
475
|
-
i0.ɵɵadvance(
|
|
476
|
-
i0.ɵɵ
|
|
477
|
-
i0.ɵɵadvance(2);
|
|
478
|
-
i0.ɵɵconditional(ctx_r2.EditMode ? 8 : -1);
|
|
479
|
-
i0.ɵɵadvance();
|
|
480
|
-
i0.ɵɵconditional(ctx_r2.PinnedItems.length === 0 && (ctx_r2.EditMode || !ctx_r2.HidePinEmptyState) ? 9 : -1);
|
|
481
|
-
i0.ɵɵadvance();
|
|
482
|
-
i0.ɵɵconditional(ctx_r2.PinnedItems.length > 0 ? 10 : -1);
|
|
491
|
+
i0.ɵɵadvance(9);
|
|
492
|
+
i0.ɵɵproperty("HeadingLevel", 1)("Label", dashboard_r30.Name)("Dashboards", ctx_r2.PinnedDashboards)("CurrentId", dashboard_r30.ID);
|
|
483
493
|
} }
|
|
484
|
-
function
|
|
494
|
+
function HomeDashboardComponent_Conditional_6_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
485
495
|
const _r32 = i0.ɵɵgetCurrentView();
|
|
486
|
-
i0.ɵɵelementStart(0, "
|
|
487
|
-
i0.ɵɵlistener("click", function
|
|
496
|
+
i0.ɵɵelementStart(0, "button", 114);
|
|
497
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_6_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r32); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnPinMenuMoveToGroup(undefined)); });
|
|
488
498
|
i0.ɵɵelementStart(1, "span");
|
|
489
499
|
i0.ɵɵtext(2, "(No group)");
|
|
490
500
|
i0.ɵɵelementEnd()();
|
|
491
501
|
} }
|
|
492
|
-
function
|
|
502
|
+
function HomeDashboardComponent_Conditional_6_For_14_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
493
503
|
const _r33 = i0.ɵɵgetCurrentView();
|
|
494
|
-
i0.ɵɵelementStart(0, "
|
|
495
|
-
i0.ɵɵlistener("click", function
|
|
504
|
+
i0.ɵɵelementStart(0, "button", 114);
|
|
505
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_6_For_14_Conditional_0_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r33); const group_r34 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnPinMenuMoveToGroup(group_r34)); });
|
|
496
506
|
i0.ɵɵelementStart(1, "span");
|
|
497
507
|
i0.ɵɵtext(2);
|
|
498
508
|
i0.ɵɵelementEnd()();
|
|
@@ -501,47 +511,54 @@ function HomeDashboardComponent_Conditional_9_For_13_Conditional_0_Template(rf,
|
|
|
501
511
|
i0.ɵɵadvance(2);
|
|
502
512
|
i0.ɵɵtextInterpolate(group_r34);
|
|
503
513
|
} }
|
|
504
|
-
function
|
|
505
|
-
i0.ɵɵconditionalCreate(0,
|
|
514
|
+
function HomeDashboardComponent_Conditional_6_For_14_Template(rf, ctx) { if (rf & 1) {
|
|
515
|
+
i0.ɵɵconditionalCreate(0, HomeDashboardComponent_Conditional_6_For_14_Conditional_0_Template, 3, 1, "button", 111);
|
|
506
516
|
} if (rf & 2) {
|
|
507
517
|
const group_r34 = ctx.$implicit;
|
|
508
518
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
509
519
|
i0.ɵɵconditional(group_r34 !== ctx_r2.PinMenuPin.Group ? 0 : -1);
|
|
510
520
|
} }
|
|
511
|
-
function
|
|
521
|
+
function HomeDashboardComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
512
522
|
const _r31 = i0.ɵɵgetCurrentView();
|
|
513
|
-
i0.ɵɵelementStart(0, "div",
|
|
514
|
-
i0.ɵɵlistener("
|
|
515
|
-
i0.ɵɵ
|
|
516
|
-
i0.ɵɵ
|
|
517
|
-
i0.ɵɵ
|
|
523
|
+
i0.ɵɵelementStart(0, "div", 105, 3);
|
|
524
|
+
i0.ɵɵlistener("keydown", function HomeDashboardComponent_Conditional_6_Template_div_keydown_0_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnPinMenuKeydown($event)); });
|
|
525
|
+
i0.ɵɵelementStart(2, "button", 106);
|
|
526
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_6_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r31); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnPinMenuEdit()); });
|
|
527
|
+
i0.ɵɵelement(3, "i", 40);
|
|
528
|
+
i0.ɵɵelementStart(4, "span");
|
|
529
|
+
i0.ɵɵtext(5, "Edit");
|
|
518
530
|
i0.ɵɵelementEnd()();
|
|
519
|
-
i0.ɵɵelement(
|
|
520
|
-
i0.ɵɵelementStart(
|
|
521
|
-
i0.ɵɵelement(
|
|
522
|
-
i0.ɵɵelementStart(
|
|
523
|
-
i0.ɵɵtext(
|
|
531
|
+
i0.ɵɵelement(6, "div", 107);
|
|
532
|
+
i0.ɵɵelementStart(7, "div", 108)(8, "div", 109);
|
|
533
|
+
i0.ɵɵelement(9, "i", 110);
|
|
534
|
+
i0.ɵɵelementStart(10, "span");
|
|
535
|
+
i0.ɵɵtext(11, "Move to Group");
|
|
524
536
|
i0.ɵɵelementEnd()();
|
|
525
|
-
i0.ɵɵconditionalCreate(
|
|
526
|
-
i0.ɵɵrepeaterCreate(
|
|
527
|
-
i0.ɵɵelementEnd();
|
|
528
|
-
i0.ɵɵelement(
|
|
529
|
-
i0.ɵɵelementStart(
|
|
530
|
-
i0.ɵɵlistener("click", function
|
|
531
|
-
i0.ɵɵelement(
|
|
532
|
-
i0.ɵɵelementStart(
|
|
533
|
-
i0.ɵɵtext(
|
|
537
|
+
i0.ɵɵconditionalCreate(12, HomeDashboardComponent_Conditional_6_Conditional_12_Template, 3, 0, "button", 111);
|
|
538
|
+
i0.ɵɵrepeaterCreate(13, HomeDashboardComponent_Conditional_6_For_14_Template, 1, 1, null, null, i0.ɵɵrepeaterTrackByIdentity);
|
|
539
|
+
i0.ɵɵelementEnd();
|
|
540
|
+
i0.ɵɵelement(15, "div", 107);
|
|
541
|
+
i0.ɵɵelementStart(16, "button", 112);
|
|
542
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_6_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r31); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnPinMenuUnpin()); });
|
|
543
|
+
i0.ɵɵelement(17, "i", 113);
|
|
544
|
+
i0.ɵɵelementStart(18, "span");
|
|
545
|
+
i0.ɵɵtext(19, "Unpin");
|
|
534
546
|
i0.ɵɵelementEnd()()();
|
|
535
547
|
} if (rf & 2) {
|
|
536
548
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
537
|
-
i0.ɵɵstyleProp("left", ctx_r2.PinMenuX, "px")("top", ctx_r2.PinMenuY, "px");
|
|
538
|
-
i0.ɵɵ
|
|
539
|
-
i0.ɵɵ
|
|
549
|
+
i0.ɵɵstyleProp("left", ctx_r2.PinMenuX, "px")("top", ctx_r2.PinMenuY, "px")("max-height", ctx_r2.PinMenuMaxHeight, "px");
|
|
550
|
+
i0.ɵɵattribute("aria-label", "Options for " + ctx_r2.PinName(ctx_r2.PinMenuPin));
|
|
551
|
+
i0.ɵɵadvance(7);
|
|
552
|
+
i0.ɵɵattribute("aria-labelledby", ctx_r2.PinMenuGroupLabelId);
|
|
553
|
+
i0.ɵɵadvance();
|
|
554
|
+
i0.ɵɵproperty("id", ctx_r2.PinMenuGroupLabelId);
|
|
555
|
+
i0.ɵɵadvance(4);
|
|
556
|
+
i0.ɵɵconditional(ctx_r2.PinMenuPin.Group ? 12 : -1);
|
|
540
557
|
i0.ɵɵadvance();
|
|
541
558
|
i0.ɵɵrepeater(ctx_r2.PinGroups);
|
|
542
559
|
} }
|
|
543
|
-
function
|
|
544
|
-
i0.ɵɵelementStart(0, "option",
|
|
560
|
+
function HomeDashboardComponent_Conditional_7_For_20_Template(rf, ctx) { if (rf & 1) {
|
|
561
|
+
i0.ɵɵelementStart(0, "option", 128);
|
|
545
562
|
i0.ɵɵtext(1);
|
|
546
563
|
i0.ɵɵelementEnd();
|
|
547
564
|
} if (rf & 2) {
|
|
@@ -550,25 +567,25 @@ function HomeDashboardComponent_Conditional_10_For_20_Template(rf, ctx) { if (rf
|
|
|
550
567
|
i0.ɵɵadvance();
|
|
551
568
|
i0.ɵɵtextInterpolate(group_r36);
|
|
552
569
|
} }
|
|
553
|
-
function
|
|
570
|
+
function HomeDashboardComponent_Conditional_7_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
554
571
|
const _r37 = i0.ɵɵgetCurrentView();
|
|
555
|
-
i0.ɵɵelementStart(0, "div",
|
|
556
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
572
|
+
i0.ɵɵelementStart(0, "div", 130)(1, "input", 133);
|
|
573
|
+
i0.ɵɵtwoWayListener("ngModelChange", function HomeDashboardComponent_Conditional_7_Conditional_23_Template_input_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r37); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.AddPanelNewGroupName, $event) || (ctx_r2.AddPanelNewGroupName = $event); return i0.ɵɵresetView($event); });
|
|
557
574
|
i0.ɵɵelementEnd()();
|
|
558
575
|
} if (rf & 2) {
|
|
559
576
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
560
577
|
i0.ɵɵadvance();
|
|
561
578
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.AddPanelNewGroupName);
|
|
562
579
|
} }
|
|
563
|
-
function
|
|
564
|
-
i0.ɵɵelementStart(0, "div",
|
|
565
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
580
|
+
function HomeDashboardComponent_Conditional_7_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
581
|
+
i0.ɵɵelementStart(0, "div", 132);
|
|
582
|
+
i0.ɵɵelement(1, "mj-loading", 134);
|
|
566
583
|
i0.ɵɵelementEnd();
|
|
567
584
|
} }
|
|
568
|
-
function
|
|
569
|
-
i0.ɵɵelement(0, "i",
|
|
585
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
586
|
+
i0.ɵɵelement(0, "i", 137);
|
|
570
587
|
i0.ɵɵtext(1, " Applications ");
|
|
571
|
-
i0.ɵɵelementStart(2, "span",
|
|
588
|
+
i0.ɵɵelementStart(2, "span", 138);
|
|
572
589
|
i0.ɵɵtext(3);
|
|
573
590
|
i0.ɵɵelementEnd();
|
|
574
591
|
} if (rf & 2) {
|
|
@@ -576,29 +593,29 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_0_ng_t
|
|
|
576
593
|
i0.ɵɵadvance(3);
|
|
577
594
|
i0.ɵɵtextInterpolate(ctx_r2.FilterApps().length);
|
|
578
595
|
} }
|
|
579
|
-
function
|
|
580
|
-
i0.ɵɵelementStart(0, "button",
|
|
581
|
-
i0.ɵɵelement(1, "i",
|
|
596
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
597
|
+
i0.ɵɵelementStart(0, "button", 147);
|
|
598
|
+
i0.ɵɵelement(1, "i", 149);
|
|
582
599
|
i0.ɵɵtext(2, " Pinned");
|
|
583
600
|
i0.ɵɵelementEnd();
|
|
584
601
|
} }
|
|
585
|
-
function
|
|
602
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
586
603
|
const _r39 = i0.ɵɵgetCurrentView();
|
|
587
|
-
i0.ɵɵelementStart(0, "button",
|
|
588
|
-
i0.ɵɵlistener("click", function
|
|
589
|
-
i0.ɵɵelement(1, "i",
|
|
604
|
+
i0.ɵɵelementStart(0, "button", 150);
|
|
605
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Conditional_8_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r39); const ni_r40 = i0.ɵɵnextContext().$implicit; const app_r41 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.PinAppNavItem(app_r41.appName, app_r41.icon, app_r41.color, ni_r40.label, ni_r40.icon)); });
|
|
606
|
+
i0.ɵɵelement(1, "i", 49);
|
|
590
607
|
i0.ɵɵtext(2, " Pin ");
|
|
591
608
|
i0.ɵɵelementEnd();
|
|
592
609
|
} }
|
|
593
|
-
function
|
|
594
|
-
i0.ɵɵelementStart(0, "div",
|
|
610
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Template(rf, ctx) { if (rf & 1) {
|
|
611
|
+
i0.ɵɵelementStart(0, "div", 142)(1, "div", 143);
|
|
595
612
|
i0.ɵɵelement(2, "i");
|
|
596
613
|
i0.ɵɵelementEnd();
|
|
597
|
-
i0.ɵɵelementStart(3, "div",
|
|
614
|
+
i0.ɵɵelementStart(3, "div", 144)(4, "div", 145);
|
|
598
615
|
i0.ɵɵtext(5);
|
|
599
616
|
i0.ɵɵelementEnd()();
|
|
600
|
-
i0.ɵɵelementStart(6, "div",
|
|
601
|
-
i0.ɵɵconditionalCreate(7,
|
|
617
|
+
i0.ɵɵelementStart(6, "div", 146);
|
|
618
|
+
i0.ɵɵconditionalCreate(7, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Conditional_7_Template, 3, 0, "button", 147)(8, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Conditional_8_Template, 3, 0, "button", 148);
|
|
602
619
|
i0.ɵɵelementEnd()();
|
|
603
620
|
} if (rf & 2) {
|
|
604
621
|
const ni_r40 = ctx.$implicit;
|
|
@@ -613,14 +630,14 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_0_ng_t
|
|
|
613
630
|
i0.ɵɵadvance(2);
|
|
614
631
|
i0.ɵɵconditional(ni_r40.pinned ? 7 : 8);
|
|
615
632
|
} }
|
|
616
|
-
function
|
|
617
|
-
i0.ɵɵelementStart(0, "div",
|
|
633
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
634
|
+
i0.ɵɵelementStart(0, "div", 139)(1, "div", 140);
|
|
618
635
|
i0.ɵɵelement(2, "i");
|
|
619
636
|
i0.ɵɵelementEnd();
|
|
620
|
-
i0.ɵɵelementStart(3, "span",
|
|
637
|
+
i0.ɵɵelementStart(3, "span", 141);
|
|
621
638
|
i0.ɵɵtext(4);
|
|
622
639
|
i0.ɵɵelementEnd()();
|
|
623
|
-
i0.ɵɵrepeaterCreate(5,
|
|
640
|
+
i0.ɵɵrepeaterCreate(5, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_For_6_Template, 9, 8, "div", 142, _forTrack3);
|
|
624
641
|
} if (rf & 2) {
|
|
625
642
|
const app_r41 = ctx.$implicit;
|
|
626
643
|
i0.ɵɵstyleProp("--panel-app-color", app_r41.color);
|
|
@@ -631,26 +648,26 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_0_ng_t
|
|
|
631
648
|
i0.ɵɵadvance();
|
|
632
649
|
i0.ɵɵrepeater(app_r41.navItems);
|
|
633
650
|
} }
|
|
634
|
-
function
|
|
635
|
-
i0.ɵɵrepeaterCreate(0,
|
|
651
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
652
|
+
i0.ɵɵrepeaterCreate(0, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_For_1_Template, 7, 5, null, null, _forTrack2);
|
|
636
653
|
} if (rf & 2) {
|
|
637
654
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
638
655
|
i0.ɵɵrepeater(ctx_r2.FilterApps());
|
|
639
656
|
} }
|
|
640
|
-
function
|
|
657
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
641
658
|
const _r38 = i0.ɵɵgetCurrentView();
|
|
642
|
-
i0.ɵɵelementStart(0, "mj-accordion-panel",
|
|
643
|
-
i0.ɵɵlistener("ExpandedChange", function
|
|
644
|
-
i0.ɵɵtemplate(1,
|
|
659
|
+
i0.ɵɵelementStart(0, "mj-accordion-panel", 136);
|
|
660
|
+
i0.ɵɵlistener("ExpandedChange", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_Template_mj_accordion_panel_ExpandedChange_0_listener($event) { i0.ɵɵrestoreView(_r38); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnPanelSectionExpandedChange("apps", $event)); });
|
|
661
|
+
i0.ɵɵtemplate(1, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_1_Template, 4, 1, "ng-template", 20)(2, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_ng_template_2_Template, 2, 0, "ng-template", 22);
|
|
645
662
|
i0.ɵɵelementEnd();
|
|
646
663
|
} if (rf & 2) {
|
|
647
664
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
648
665
|
i0.ɵɵproperty("FlushBody", true)("Expanded", !ctx_r2.PanelSectionCollapsed["apps"]);
|
|
649
666
|
} }
|
|
650
|
-
function
|
|
651
|
-
i0.ɵɵelement(0, "i",
|
|
667
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
668
|
+
i0.ɵɵelement(0, "i", 151);
|
|
652
669
|
i0.ɵɵtext(1, " Dashboards ");
|
|
653
|
-
i0.ɵɵelementStart(2, "span",
|
|
670
|
+
i0.ɵɵelementStart(2, "span", 138);
|
|
654
671
|
i0.ɵɵtext(3);
|
|
655
672
|
i0.ɵɵelementEnd();
|
|
656
673
|
} if (rf & 2) {
|
|
@@ -658,29 +675,29 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_1_ng_t
|
|
|
658
675
|
i0.ɵɵadvance(3);
|
|
659
676
|
i0.ɵɵtextInterpolate(ctx_r2.FilterPanelItems(ctx_r2.AvailableDashboards).length);
|
|
660
677
|
} }
|
|
661
|
-
function
|
|
662
|
-
i0.ɵɵelementStart(0, "button",
|
|
663
|
-
i0.ɵɵelement(1, "i",
|
|
678
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
679
|
+
i0.ɵɵelementStart(0, "button", 147);
|
|
680
|
+
i0.ɵɵelement(1, "i", 149);
|
|
664
681
|
i0.ɵɵtext(2, " Pinned");
|
|
665
682
|
i0.ɵɵelementEnd();
|
|
666
683
|
} }
|
|
667
|
-
function
|
|
684
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
668
685
|
const _r43 = i0.ɵɵgetCurrentView();
|
|
669
|
-
i0.ɵɵelementStart(0, "button",
|
|
670
|
-
i0.ɵɵlistener("click", function
|
|
671
|
-
i0.ɵɵelement(1, "i",
|
|
686
|
+
i0.ɵɵelementStart(0, "button", 150);
|
|
687
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Conditional_8_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r43); const item_r44 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.PinFromPanel("Dashboards", item_r44.id, item_r44.name)); });
|
|
688
|
+
i0.ɵɵelement(1, "i", 49);
|
|
672
689
|
i0.ɵɵtext(2, " Pin ");
|
|
673
690
|
i0.ɵɵelementEnd();
|
|
674
691
|
} }
|
|
675
|
-
function
|
|
676
|
-
i0.ɵɵelementStart(0, "div",
|
|
677
|
-
i0.ɵɵelement(2, "i",
|
|
692
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
693
|
+
i0.ɵɵelementStart(0, "div", 152)(1, "div", 153);
|
|
694
|
+
i0.ɵɵelement(2, "i", 154);
|
|
678
695
|
i0.ɵɵelementEnd();
|
|
679
|
-
i0.ɵɵelementStart(3, "div",
|
|
696
|
+
i0.ɵɵelementStart(3, "div", 144)(4, "div", 145);
|
|
680
697
|
i0.ɵɵtext(5);
|
|
681
698
|
i0.ɵɵelementEnd()();
|
|
682
|
-
i0.ɵɵelementStart(6, "div",
|
|
683
|
-
i0.ɵɵconditionalCreate(7,
|
|
699
|
+
i0.ɵɵelementStart(6, "div", 146);
|
|
700
|
+
i0.ɵɵconditionalCreate(7, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Conditional_7_Template, 3, 0, "button", 147)(8, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Conditional_8_Template, 3, 0, "button", 148);
|
|
684
701
|
i0.ɵɵelementEnd()();
|
|
685
702
|
} if (rf & 2) {
|
|
686
703
|
const item_r44 = ctx.$implicit;
|
|
@@ -689,26 +706,26 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_1_ng_t
|
|
|
689
706
|
i0.ɵɵadvance(2);
|
|
690
707
|
i0.ɵɵconditional(item_r44.pinned ? 7 : 8);
|
|
691
708
|
} }
|
|
692
|
-
function
|
|
693
|
-
i0.ɵɵrepeaterCreate(0,
|
|
709
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
710
|
+
i0.ɵɵrepeaterCreate(0, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_For_1_Template, 9, 2, "div", 152, _forTrack4);
|
|
694
711
|
} if (rf & 2) {
|
|
695
712
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
696
713
|
i0.ɵɵrepeater(ctx_r2.FilterPanelItems(ctx_r2.AvailableDashboards));
|
|
697
714
|
} }
|
|
698
|
-
function
|
|
715
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
699
716
|
const _r42 = i0.ɵɵgetCurrentView();
|
|
700
|
-
i0.ɵɵelementStart(0, "mj-accordion-panel",
|
|
701
|
-
i0.ɵɵlistener("ExpandedChange", function
|
|
702
|
-
i0.ɵɵtemplate(1,
|
|
717
|
+
i0.ɵɵelementStart(0, "mj-accordion-panel", 136);
|
|
718
|
+
i0.ɵɵlistener("ExpandedChange", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_Template_mj_accordion_panel_ExpandedChange_0_listener($event) { i0.ɵɵrestoreView(_r42); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnPanelSectionExpandedChange("dashboards", $event)); });
|
|
719
|
+
i0.ɵɵtemplate(1, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_1_Template, 4, 1, "ng-template", 20)(2, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_ng_template_2_Template, 2, 0, "ng-template", 22);
|
|
703
720
|
i0.ɵɵelementEnd();
|
|
704
721
|
} if (rf & 2) {
|
|
705
722
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
706
723
|
i0.ɵɵproperty("FlushBody", true)("Expanded", !ctx_r2.PanelSectionCollapsed["dashboards"]);
|
|
707
724
|
} }
|
|
708
|
-
function
|
|
709
|
-
i0.ɵɵelement(0, "i",
|
|
725
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
726
|
+
i0.ɵɵelement(0, "i", 155);
|
|
710
727
|
i0.ɵɵtext(1, " Views ");
|
|
711
|
-
i0.ɵɵelementStart(2, "span",
|
|
728
|
+
i0.ɵɵelementStart(2, "span", 138);
|
|
712
729
|
i0.ɵɵtext(3);
|
|
713
730
|
i0.ɵɵelementEnd();
|
|
714
731
|
} if (rf & 2) {
|
|
@@ -716,32 +733,32 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_2_ng_t
|
|
|
716
733
|
i0.ɵɵadvance(3);
|
|
717
734
|
i0.ɵɵtextInterpolate(ctx_r2.FilterPanelItems(ctx_r2.AvailableViews).length);
|
|
718
735
|
} }
|
|
719
|
-
function
|
|
720
|
-
i0.ɵɵelementStart(0, "button",
|
|
721
|
-
i0.ɵɵelement(1, "i",
|
|
736
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
737
|
+
i0.ɵɵelementStart(0, "button", 147);
|
|
738
|
+
i0.ɵɵelement(1, "i", 149);
|
|
722
739
|
i0.ɵɵtext(2, " Pinned");
|
|
723
740
|
i0.ɵɵelementEnd();
|
|
724
741
|
} }
|
|
725
|
-
function
|
|
742
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
726
743
|
const _r46 = i0.ɵɵgetCurrentView();
|
|
727
|
-
i0.ɵɵelementStart(0, "button",
|
|
728
|
-
i0.ɵɵlistener("click", function
|
|
729
|
-
i0.ɵɵelement(1, "i",
|
|
744
|
+
i0.ɵɵelementStart(0, "button", 150);
|
|
745
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r46); const item_r47 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.PinFromPanel("User Views", item_r47.id, item_r47.name)); });
|
|
746
|
+
i0.ɵɵelement(1, "i", 49);
|
|
730
747
|
i0.ɵɵtext(2, " Pin ");
|
|
731
748
|
i0.ɵɵelementEnd();
|
|
732
749
|
} }
|
|
733
|
-
function
|
|
734
|
-
i0.ɵɵelementStart(0, "div",
|
|
735
|
-
i0.ɵɵelement(2, "i",
|
|
750
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
751
|
+
i0.ɵɵelementStart(0, "div", 152)(1, "div", 153);
|
|
752
|
+
i0.ɵɵelement(2, "i", 156);
|
|
736
753
|
i0.ɵɵelementEnd();
|
|
737
|
-
i0.ɵɵelementStart(3, "div",
|
|
754
|
+
i0.ɵɵelementStart(3, "div", 144)(4, "div", 145);
|
|
738
755
|
i0.ɵɵtext(5);
|
|
739
756
|
i0.ɵɵelementEnd();
|
|
740
|
-
i0.ɵɵelementStart(6, "div",
|
|
757
|
+
i0.ɵɵelementStart(6, "div", 157);
|
|
741
758
|
i0.ɵɵtext(7);
|
|
742
759
|
i0.ɵɵelementEnd()();
|
|
743
|
-
i0.ɵɵelementStart(8, "div",
|
|
744
|
-
i0.ɵɵconditionalCreate(9,
|
|
760
|
+
i0.ɵɵelementStart(8, "div", 146);
|
|
761
|
+
i0.ɵɵconditionalCreate(9, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Conditional_9_Template, 3, 0, "button", 147)(10, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Conditional_10_Template, 3, 0, "button", 148);
|
|
745
762
|
i0.ɵɵelementEnd()();
|
|
746
763
|
} if (rf & 2) {
|
|
747
764
|
const item_r47 = ctx.$implicit;
|
|
@@ -752,26 +769,26 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_2_ng_t
|
|
|
752
769
|
i0.ɵɵadvance(2);
|
|
753
770
|
i0.ɵɵconditional(item_r47.pinned ? 9 : 10);
|
|
754
771
|
} }
|
|
755
|
-
function
|
|
756
|
-
i0.ɵɵrepeaterCreate(0,
|
|
772
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
773
|
+
i0.ɵɵrepeaterCreate(0, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_For_1_Template, 11, 3, "div", 152, _forTrack4);
|
|
757
774
|
} if (rf & 2) {
|
|
758
775
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
759
776
|
i0.ɵɵrepeater(ctx_r2.FilterPanelItems(ctx_r2.AvailableViews));
|
|
760
777
|
} }
|
|
761
|
-
function
|
|
778
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
762
779
|
const _r45 = i0.ɵɵgetCurrentView();
|
|
763
|
-
i0.ɵɵelementStart(0, "mj-accordion-panel",
|
|
764
|
-
i0.ɵɵlistener("ExpandedChange", function
|
|
765
|
-
i0.ɵɵtemplate(1,
|
|
780
|
+
i0.ɵɵelementStart(0, "mj-accordion-panel", 136);
|
|
781
|
+
i0.ɵɵlistener("ExpandedChange", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_Template_mj_accordion_panel_ExpandedChange_0_listener($event) { i0.ɵɵrestoreView(_r45); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnPanelSectionExpandedChange("views", $event)); });
|
|
782
|
+
i0.ɵɵtemplate(1, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_1_Template, 4, 1, "ng-template", 20)(2, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_ng_template_2_Template, 2, 0, "ng-template", 22);
|
|
766
783
|
i0.ɵɵelementEnd();
|
|
767
784
|
} if (rf & 2) {
|
|
768
785
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
769
786
|
i0.ɵɵproperty("FlushBody", true)("Expanded", !ctx_r2.PanelSectionCollapsed["views"]);
|
|
770
787
|
} }
|
|
771
|
-
function
|
|
772
|
-
i0.ɵɵelement(0, "i",
|
|
788
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
789
|
+
i0.ɵɵelement(0, "i", 158);
|
|
773
790
|
i0.ɵɵtext(1, " Queries ");
|
|
774
|
-
i0.ɵɵelementStart(2, "span",
|
|
791
|
+
i0.ɵɵelementStart(2, "span", 138);
|
|
775
792
|
i0.ɵɵtext(3);
|
|
776
793
|
i0.ɵɵelementEnd();
|
|
777
794
|
} if (rf & 2) {
|
|
@@ -779,29 +796,29 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_3_ng_t
|
|
|
779
796
|
i0.ɵɵadvance(3);
|
|
780
797
|
i0.ɵɵtextInterpolate(ctx_r2.FilterPanelItems(ctx_r2.AvailableQueries).length);
|
|
781
798
|
} }
|
|
782
|
-
function
|
|
783
|
-
i0.ɵɵelementStart(0, "button",
|
|
784
|
-
i0.ɵɵelement(1, "i",
|
|
799
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
800
|
+
i0.ɵɵelementStart(0, "button", 147);
|
|
801
|
+
i0.ɵɵelement(1, "i", 149);
|
|
785
802
|
i0.ɵɵtext(2, " Pinned");
|
|
786
803
|
i0.ɵɵelementEnd();
|
|
787
804
|
} }
|
|
788
|
-
function
|
|
805
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
789
806
|
const _r49 = i0.ɵɵgetCurrentView();
|
|
790
|
-
i0.ɵɵelementStart(0, "button",
|
|
791
|
-
i0.ɵɵlistener("click", function
|
|
792
|
-
i0.ɵɵelement(1, "i",
|
|
807
|
+
i0.ɵɵelementStart(0, "button", 150);
|
|
808
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Conditional_8_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r49); const item_r50 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.PinFromPanel("Queries", item_r50.id, item_r50.name)); });
|
|
809
|
+
i0.ɵɵelement(1, "i", 49);
|
|
793
810
|
i0.ɵɵtext(2, " Pin ");
|
|
794
811
|
i0.ɵɵelementEnd();
|
|
795
812
|
} }
|
|
796
|
-
function
|
|
797
|
-
i0.ɵɵelementStart(0, "div",
|
|
798
|
-
i0.ɵɵelement(2, "i",
|
|
813
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
814
|
+
i0.ɵɵelementStart(0, "div", 152)(1, "div", 153);
|
|
815
|
+
i0.ɵɵelement(2, "i", 159);
|
|
799
816
|
i0.ɵɵelementEnd();
|
|
800
|
-
i0.ɵɵelementStart(3, "div",
|
|
817
|
+
i0.ɵɵelementStart(3, "div", 144)(4, "div", 145);
|
|
801
818
|
i0.ɵɵtext(5);
|
|
802
819
|
i0.ɵɵelementEnd()();
|
|
803
|
-
i0.ɵɵelementStart(6, "div",
|
|
804
|
-
i0.ɵɵconditionalCreate(7,
|
|
820
|
+
i0.ɵɵelementStart(6, "div", 146);
|
|
821
|
+
i0.ɵɵconditionalCreate(7, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Conditional_7_Template, 3, 0, "button", 147)(8, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Conditional_8_Template, 3, 0, "button", 148);
|
|
805
822
|
i0.ɵɵelementEnd()();
|
|
806
823
|
} if (rf & 2) {
|
|
807
824
|
const item_r50 = ctx.$implicit;
|
|
@@ -810,26 +827,26 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_3_ng_t
|
|
|
810
827
|
i0.ɵɵadvance(2);
|
|
811
828
|
i0.ɵɵconditional(item_r50.pinned ? 7 : 8);
|
|
812
829
|
} }
|
|
813
|
-
function
|
|
814
|
-
i0.ɵɵrepeaterCreate(0,
|
|
830
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
831
|
+
i0.ɵɵrepeaterCreate(0, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_For_1_Template, 9, 2, "div", 152, _forTrack4);
|
|
815
832
|
} if (rf & 2) {
|
|
816
833
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
817
834
|
i0.ɵɵrepeater(ctx_r2.FilterPanelItems(ctx_r2.AvailableQueries));
|
|
818
835
|
} }
|
|
819
|
-
function
|
|
836
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
820
837
|
const _r48 = i0.ɵɵgetCurrentView();
|
|
821
|
-
i0.ɵɵelementStart(0, "mj-accordion-panel",
|
|
822
|
-
i0.ɵɵlistener("ExpandedChange", function
|
|
823
|
-
i0.ɵɵtemplate(1,
|
|
838
|
+
i0.ɵɵelementStart(0, "mj-accordion-panel", 136);
|
|
839
|
+
i0.ɵɵlistener("ExpandedChange", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_Template_mj_accordion_panel_ExpandedChange_0_listener($event) { i0.ɵɵrestoreView(_r48); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnPanelSectionExpandedChange("queries", $event)); });
|
|
840
|
+
i0.ɵɵtemplate(1, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_1_Template, 4, 1, "ng-template", 20)(2, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_ng_template_2_Template, 2, 0, "ng-template", 22);
|
|
824
841
|
i0.ɵɵelementEnd();
|
|
825
842
|
} if (rf & 2) {
|
|
826
843
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
827
844
|
i0.ɵɵproperty("FlushBody", true)("Expanded", !ctx_r2.PanelSectionCollapsed["queries"]);
|
|
828
845
|
} }
|
|
829
|
-
function
|
|
830
|
-
i0.ɵɵelement(0, "i",
|
|
846
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
847
|
+
i0.ɵɵelement(0, "i", 160);
|
|
831
848
|
i0.ɵɵtext(1, " Quick Actions ");
|
|
832
|
-
i0.ɵɵelementStart(2, "span",
|
|
849
|
+
i0.ɵɵelementStart(2, "span", 138);
|
|
833
850
|
i0.ɵɵtext(3);
|
|
834
851
|
i0.ɵɵelementEnd();
|
|
835
852
|
} if (rf & 2) {
|
|
@@ -837,8 +854,8 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_4_ng_t
|
|
|
837
854
|
i0.ɵɵadvance(3);
|
|
838
855
|
i0.ɵɵtextInterpolate(ctx_r2.FilterPanelItems(ctx_r2.AvailableActions).length);
|
|
839
856
|
} }
|
|
840
|
-
function
|
|
841
|
-
i0.ɵɵelementStart(0, "div",
|
|
857
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_For_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
858
|
+
i0.ɵɵelementStart(0, "div", 157);
|
|
842
859
|
i0.ɵɵtext(1);
|
|
843
860
|
i0.ɵɵelementEnd();
|
|
844
861
|
} if (rf & 2) {
|
|
@@ -846,19 +863,19 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_4_ng_t
|
|
|
846
863
|
i0.ɵɵadvance();
|
|
847
864
|
i0.ɵɵtextInterpolate(item_r53.description);
|
|
848
865
|
} }
|
|
849
|
-
function
|
|
866
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
850
867
|
const _r52 = i0.ɵɵgetCurrentView();
|
|
851
|
-
i0.ɵɵelementStart(0, "div",
|
|
852
|
-
i0.ɵɵelement(2, "i",
|
|
868
|
+
i0.ɵɵelementStart(0, "div", 152)(1, "div", 153);
|
|
869
|
+
i0.ɵɵelement(2, "i", 161);
|
|
853
870
|
i0.ɵɵelementEnd();
|
|
854
|
-
i0.ɵɵelementStart(3, "div",
|
|
871
|
+
i0.ɵɵelementStart(3, "div", 144)(4, "div", 145);
|
|
855
872
|
i0.ɵɵtext(5);
|
|
856
873
|
i0.ɵɵelementEnd();
|
|
857
|
-
i0.ɵɵconditionalCreate(6,
|
|
874
|
+
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_For_1_Conditional_6_Template, 2, 1, "div", 157);
|
|
858
875
|
i0.ɵɵelementEnd();
|
|
859
|
-
i0.ɵɵelementStart(7, "div",
|
|
860
|
-
i0.ɵɵlistener("click", function
|
|
861
|
-
i0.ɵɵelement(9, "i",
|
|
876
|
+
i0.ɵɵelementStart(7, "div", 146)(8, "button", 150);
|
|
877
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_For_1_Template_button_click_8_listener() { const item_r53 = i0.ɵɵrestoreView(_r52).$implicit; const ctx_r2 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r2.OpenActionPinConfig(item_r53.id, item_r53.name, item_r53.description)); });
|
|
878
|
+
i0.ɵɵelement(9, "i", 162);
|
|
862
879
|
i0.ɵɵtext(10, " Configure ");
|
|
863
880
|
i0.ɵɵelementEnd()()();
|
|
864
881
|
} if (rf & 2) {
|
|
@@ -868,28 +885,28 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Conditional_4_ng_t
|
|
|
868
885
|
i0.ɵɵadvance();
|
|
869
886
|
i0.ɵɵconditional(item_r53.description ? 6 : -1);
|
|
870
887
|
} }
|
|
871
|
-
function
|
|
872
|
-
i0.ɵɵrepeaterCreate(0,
|
|
888
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
889
|
+
i0.ɵɵrepeaterCreate(0, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_For_1_Template, 11, 2, "div", 152, _forTrack4);
|
|
873
890
|
} if (rf & 2) {
|
|
874
891
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
875
892
|
i0.ɵɵrepeater(ctx_r2.FilterPanelItems(ctx_r2.AvailableActions));
|
|
876
893
|
} }
|
|
877
|
-
function
|
|
894
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
878
895
|
const _r51 = i0.ɵɵgetCurrentView();
|
|
879
|
-
i0.ɵɵelementStart(0, "mj-accordion-panel",
|
|
880
|
-
i0.ɵɵlistener("ExpandedChange", function
|
|
881
|
-
i0.ɵɵtemplate(1,
|
|
896
|
+
i0.ɵɵelementStart(0, "mj-accordion-panel", 136);
|
|
897
|
+
i0.ɵɵlistener("ExpandedChange", function HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_Template_mj_accordion_panel_ExpandedChange_0_listener($event) { i0.ɵɵrestoreView(_r51); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnPanelSectionExpandedChange("actions", $event)); });
|
|
898
|
+
i0.ɵɵtemplate(1, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_1_Template, 4, 1, "ng-template", 20)(2, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_ng_template_2_Template, 2, 0, "ng-template", 22);
|
|
882
899
|
i0.ɵɵelementEnd();
|
|
883
900
|
} if (rf & 2) {
|
|
884
901
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
885
902
|
i0.ɵɵproperty("FlushBody", true)("Expanded", !ctx_r2.PanelSectionCollapsed["actions"]);
|
|
886
903
|
} }
|
|
887
|
-
function
|
|
888
|
-
i0.ɵɵconditionalCreate(0,
|
|
889
|
-
i0.ɵɵconditionalCreate(1,
|
|
890
|
-
i0.ɵɵconditionalCreate(2,
|
|
891
|
-
i0.ɵɵconditionalCreate(3,
|
|
892
|
-
i0.ɵɵconditionalCreate(4,
|
|
904
|
+
function HomeDashboardComponent_Conditional_7_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
905
|
+
i0.ɵɵconditionalCreate(0, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_0_Template, 3, 2, "mj-accordion-panel", 135);
|
|
906
|
+
i0.ɵɵconditionalCreate(1, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_1_Template, 3, 2, "mj-accordion-panel", 135);
|
|
907
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_2_Template, 3, 2, "mj-accordion-panel", 135);
|
|
908
|
+
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_3_Template, 3, 2, "mj-accordion-panel", 135);
|
|
909
|
+
i0.ɵɵconditionalCreate(4, HomeDashboardComponent_Conditional_7_Conditional_26_Conditional_4_Template, 3, 2, "mj-accordion-panel", 135);
|
|
893
910
|
} if (rf & 2) {
|
|
894
911
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
895
912
|
i0.ɵɵconditional(ctx_r2.FilterApps().length > 0 ? 0 : -1);
|
|
@@ -902,40 +919,40 @@ function HomeDashboardComponent_Conditional_10_Conditional_26_Template(rf, ctx)
|
|
|
902
919
|
i0.ɵɵadvance();
|
|
903
920
|
i0.ɵɵconditional(ctx_r2.FilterPanelItems(ctx_r2.AvailableActions).length > 0 ? 4 : -1);
|
|
904
921
|
} }
|
|
905
|
-
function
|
|
922
|
+
function HomeDashboardComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
906
923
|
const _r35 = i0.ɵɵgetCurrentView();
|
|
907
|
-
i0.ɵɵelementStart(0, "div",
|
|
908
|
-
i0.ɵɵlistener("click", function
|
|
924
|
+
i0.ɵɵelementStart(0, "div", 115);
|
|
925
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r35); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseAddPinPanel()); });
|
|
909
926
|
i0.ɵɵelementEnd();
|
|
910
|
-
i0.ɵɵelementStart(1, "div",
|
|
911
|
-
i0.ɵɵelement(4, "i",
|
|
927
|
+
i0.ɵɵelementStart(1, "div", 116)(2, "div", 117)(3, "h3");
|
|
928
|
+
i0.ɵɵelement(4, "i", 118);
|
|
912
929
|
i0.ɵɵtext(5, " Add Pin");
|
|
913
930
|
i0.ɵɵelementEnd();
|
|
914
|
-
i0.ɵɵelementStart(6, "button",
|
|
915
|
-
i0.ɵɵlistener("click", function
|
|
916
|
-
i0.ɵɵelement(7, "i",
|
|
931
|
+
i0.ɵɵelementStart(6, "button", 119);
|
|
932
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_7_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r35); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseAddPinPanel()); });
|
|
933
|
+
i0.ɵɵelement(7, "i", 52);
|
|
917
934
|
i0.ɵɵelementEnd()();
|
|
918
|
-
i0.ɵɵelementStart(8, "div",
|
|
919
|
-
i0.ɵɵelement(10, "i",
|
|
920
|
-
i0.ɵɵelementStart(11, "input",
|
|
921
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
935
|
+
i0.ɵɵelementStart(8, "div", 120)(9, "div", 121);
|
|
936
|
+
i0.ɵɵelement(10, "i", 122);
|
|
937
|
+
i0.ɵɵelementStart(11, "input", 123);
|
|
938
|
+
i0.ɵɵtwoWayListener("ngModelChange", function HomeDashboardComponent_Conditional_7_Template_input_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r35); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.AddPanelSearchQuery, $event) || (ctx_r2.AddPanelSearchQuery = $event); return i0.ɵɵresetView($event); });
|
|
922
939
|
i0.ɵɵelementEnd()()();
|
|
923
|
-
i0.ɵɵelementStart(12, "div",
|
|
924
|
-
i0.ɵɵelement(14, "i",
|
|
940
|
+
i0.ɵɵelementStart(12, "div", 124)(13, "label");
|
|
941
|
+
i0.ɵɵelement(14, "i", 125);
|
|
925
942
|
i0.ɵɵtext(15, " Add to group:");
|
|
926
943
|
i0.ɵɵelementEnd();
|
|
927
|
-
i0.ɵɵelementStart(16, "select",
|
|
928
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
929
|
-
i0.ɵɵelementStart(17, "option",
|
|
944
|
+
i0.ɵɵelementStart(16, "select", 126);
|
|
945
|
+
i0.ɵɵtwoWayListener("ngModelChange", function HomeDashboardComponent_Conditional_7_Template_select_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r35); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.AddPanelSelectedGroup, $event) || (ctx_r2.AddPanelSelectedGroup = $event); return i0.ɵɵresetView($event); });
|
|
946
|
+
i0.ɵɵelementStart(17, "option", 127);
|
|
930
947
|
i0.ɵɵtext(18, "(No group)");
|
|
931
948
|
i0.ɵɵelementEnd();
|
|
932
|
-
i0.ɵɵrepeaterCreate(19,
|
|
933
|
-
i0.ɵɵelementStart(21, "option",
|
|
949
|
+
i0.ɵɵrepeaterCreate(19, HomeDashboardComponent_Conditional_7_For_20_Template, 2, 2, "option", 128, i0.ɵɵrepeaterTrackByIdentity);
|
|
950
|
+
i0.ɵɵelementStart(21, "option", 129);
|
|
934
951
|
i0.ɵɵtext(22, "+ New group...");
|
|
935
952
|
i0.ɵɵelementEnd()()();
|
|
936
|
-
i0.ɵɵconditionalCreate(23,
|
|
937
|
-
i0.ɵɵelementStart(24, "div",
|
|
938
|
-
i0.ɵɵconditionalCreate(25,
|
|
953
|
+
i0.ɵɵconditionalCreate(23, HomeDashboardComponent_Conditional_7_Conditional_23_Template, 2, 1, "div", 130);
|
|
954
|
+
i0.ɵɵelementStart(24, "div", 131);
|
|
955
|
+
i0.ɵɵconditionalCreate(25, HomeDashboardComponent_Conditional_7_Conditional_25_Template, 2, 0, "div", 132)(26, HomeDashboardComponent_Conditional_7_Conditional_26_Template, 5, 5);
|
|
939
956
|
i0.ɵɵelementEnd()();
|
|
940
957
|
} if (rf & 2) {
|
|
941
958
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -950,134 +967,39 @@ function HomeDashboardComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
|
950
967
|
i0.ɵɵadvance(2);
|
|
951
968
|
i0.ɵɵconditional(ctx_r2.AddPanelLoading ? 25 : 26);
|
|
952
969
|
} }
|
|
953
|
-
function
|
|
954
|
-
i0.ɵɵelementStart(0, "div",
|
|
955
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
956
|
-
i0.ɵɵelementEnd();
|
|
957
|
-
} }
|
|
958
|
-
function HomeDashboardComponent_Conditional_14_For_6_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
959
|
-
i0.ɵɵelementStart(0, "p", 141);
|
|
960
|
-
i0.ɵɵtext(1);
|
|
961
|
-
i0.ɵɵelementEnd();
|
|
962
|
-
} if (rf & 2) {
|
|
963
|
-
const appData_r55 = i0.ɵɵnextContext().$implicit;
|
|
964
|
-
i0.ɵɵadvance();
|
|
965
|
-
i0.ɵɵtextInterpolate(appData_r55.app.Description);
|
|
966
|
-
} }
|
|
967
|
-
function HomeDashboardComponent_Conditional_14_For_6_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
968
|
-
i0.ɵɵelementStart(0, "div", 145);
|
|
969
|
-
i0.ɵɵelement(1, "i");
|
|
970
|
-
i0.ɵɵelementStart(2, "span");
|
|
971
|
-
i0.ɵɵtext(3);
|
|
972
|
-
i0.ɵɵelementEnd()();
|
|
973
|
-
} if (rf & 2) {
|
|
974
|
-
const item_r56 = ctx.$implicit;
|
|
975
|
-
i0.ɵɵadvance();
|
|
976
|
-
i0.ɵɵclassMap(item_r56.Icon);
|
|
977
|
-
i0.ɵɵadvance(2);
|
|
978
|
-
i0.ɵɵtextInterpolate(item_r56.Label);
|
|
979
|
-
} }
|
|
980
|
-
function HomeDashboardComponent_Conditional_14_For_6_Conditional_8_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
981
|
-
i0.ɵɵelementStart(0, "span", 146);
|
|
982
|
-
i0.ɵɵtext(1);
|
|
983
|
-
i0.ɵɵelementEnd();
|
|
984
|
-
} if (rf & 2) {
|
|
985
|
-
const appData_r55 = i0.ɵɵnextContext(2).$implicit;
|
|
986
|
-
i0.ɵɵadvance();
|
|
987
|
-
i0.ɵɵtextInterpolate1(" +", appData_r55.moreItemsCount, " more ");
|
|
988
|
-
} }
|
|
989
|
-
function HomeDashboardComponent_Conditional_14_For_6_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
990
|
-
i0.ɵɵelementStart(0, "div", 142);
|
|
991
|
-
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_14_For_6_Conditional_8_For_2_Template, 4, 3, "div", 145, i0.ɵɵcomponentInstance().trackByNavItem, true);
|
|
992
|
-
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_14_For_6_Conditional_8_Conditional_3_Template, 2, 1, "span", 146);
|
|
993
|
-
i0.ɵɵelementEnd();
|
|
994
|
-
} if (rf & 2) {
|
|
995
|
-
const appData_r55 = i0.ɵɵnextContext().$implicit;
|
|
996
|
-
i0.ɵɵadvance();
|
|
997
|
-
i0.ɵɵrepeater(appData_r55.navItemsPreview);
|
|
998
|
-
i0.ɵɵadvance(2);
|
|
999
|
-
i0.ɵɵconditional(appData_r55.showMoreItems ? 3 : -1);
|
|
1000
|
-
} }
|
|
1001
|
-
function HomeDashboardComponent_Conditional_14_For_6_Template(rf, ctx) { if (rf & 1) {
|
|
1002
|
-
const _r54 = i0.ɵɵgetCurrentView();
|
|
1003
|
-
i0.ɵɵelementStart(0, "div", 136);
|
|
1004
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_14_For_6_Template_div_click_0_listener() { const appData_r55 = i0.ɵɵrestoreView(_r54).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onAppClick(appData_r55.app)); });
|
|
1005
|
-
i0.ɵɵelementStart(1, "div", 137)(2, "div", 138);
|
|
1006
|
-
i0.ɵɵelement(3, "i");
|
|
1007
|
-
i0.ɵɵelementEnd()();
|
|
1008
|
-
i0.ɵɵelementStart(4, "div", 139)(5, "h3", 140);
|
|
1009
|
-
i0.ɵɵtext(6);
|
|
1010
|
-
i0.ɵɵelementEnd();
|
|
1011
|
-
i0.ɵɵconditionalCreate(7, HomeDashboardComponent_Conditional_14_For_6_Conditional_7_Template, 2, 1, "p", 141);
|
|
1012
|
-
i0.ɵɵconditionalCreate(8, HomeDashboardComponent_Conditional_14_For_6_Conditional_8_Template, 4, 1, "div", 142);
|
|
1013
|
-
i0.ɵɵelementEnd();
|
|
1014
|
-
i0.ɵɵelementStart(9, "div", 143);
|
|
1015
|
-
i0.ɵɵelement(10, "i", 144);
|
|
1016
|
-
i0.ɵɵelementEnd()();
|
|
1017
|
-
} if (rf & 2) {
|
|
1018
|
-
const appData_r55 = ctx.$implicit;
|
|
1019
|
-
i0.ɵɵstyleProp("--app-color", appData_r55.color);
|
|
1020
|
-
i0.ɵɵproperty("mjClickable", appData_r55.app.Name)("testId", "app-tile-" + appData_r55.app.Name);
|
|
1021
|
-
i0.ɵɵadvance(3);
|
|
1022
|
-
i0.ɵɵclassMap(appData_r55.icon);
|
|
1023
|
-
i0.ɵɵadvance(3);
|
|
1024
|
-
i0.ɵɵtextInterpolate(appData_r55.app.Name);
|
|
1025
|
-
i0.ɵɵadvance();
|
|
1026
|
-
i0.ɵɵconditional(appData_r55.app.Description ? 7 : -1);
|
|
1027
|
-
i0.ɵɵadvance();
|
|
1028
|
-
i0.ɵɵconditional(appData_r55.navItemsCount > 0 ? 8 : -1);
|
|
1029
|
-
} }
|
|
1030
|
-
function HomeDashboardComponent_Conditional_14_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
1031
|
-
const _r57 = i0.ɵɵgetCurrentView();
|
|
1032
|
-
i0.ɵɵelementStart(0, "mj-empty-state", 147);
|
|
1033
|
-
i0.ɵɵlistener("Action", function HomeDashboardComponent_Conditional_14_Conditional_7_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r57); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.openConfigDialog()); });
|
|
970
|
+
function HomeDashboardComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
971
|
+
i0.ɵɵelementStart(0, "div", 12);
|
|
972
|
+
i0.ɵɵelement(1, "mj-loading", 163);
|
|
1034
973
|
i0.ɵɵelementEnd();
|
|
1035
974
|
} }
|
|
1036
|
-
function
|
|
1037
|
-
i0.ɵɵ
|
|
1038
|
-
i0.ɵɵ
|
|
1039
|
-
i0.ɵɵ
|
|
1040
|
-
i0.ɵɵ
|
|
1041
|
-
i0.ɵɵelementStart(4, "div", 133);
|
|
1042
|
-
i0.ɵɵrepeaterCreate(5, HomeDashboardComponent_Conditional_14_For_6_Template, 11, 9, "div", 134, i0.ɵɵcomponentInstance().trackByApp, true);
|
|
1043
|
-
i0.ɵɵelementEnd();
|
|
1044
|
-
i0.ɵɵconditionalCreate(7, HomeDashboardComponent_Conditional_14_Conditional_7_Template, 1, 0, "mj-empty-state", 135);
|
|
1045
|
-
i0.ɵɵelementEnd();
|
|
1046
|
-
} if (rf & 2) {
|
|
1047
|
-
const ctx_r2 = i0.ɵɵnextContext();
|
|
1048
|
-
i0.ɵɵadvance(5);
|
|
1049
|
-
i0.ɵɵrepeater(ctx_r2.appsDisplayData);
|
|
1050
|
-
i0.ɵɵadvance(2);
|
|
1051
|
-
i0.ɵɵconditional(ctx_r2.apps.length === 0 ? 7 : -1);
|
|
1052
|
-
} }
|
|
1053
|
-
function HomeDashboardComponent_Conditional_15_Conditional_8_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
1054
|
-
const _r59 = i0.ɵɵgetCurrentView();
|
|
1055
|
-
i0.ɵɵelementStart(0, "div", 160);
|
|
1056
|
-
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_15_Conditional_8_For_8_Template_div_click_0_listener() { const notification_r60 = i0.ɵɵrestoreView(_r59).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onNotificationClick(notification_r60)); });
|
|
1057
|
-
i0.ɵɵelementStart(1, "div", 161)(2, "span", 162);
|
|
975
|
+
function HomeDashboardComponent_Conditional_12_Conditional_8_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
976
|
+
const _r55 = i0.ɵɵgetCurrentView();
|
|
977
|
+
i0.ɵɵelementStart(0, "div", 176);
|
|
978
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_12_Conditional_8_For_8_Template_div_click_0_listener() { const notification_r56 = i0.ɵɵrestoreView(_r55).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onNotificationClick(notification_r56)); });
|
|
979
|
+
i0.ɵɵelementStart(1, "div", 177)(2, "span", 178);
|
|
1058
980
|
i0.ɵɵtext(3);
|
|
1059
981
|
i0.ɵɵelementEnd();
|
|
1060
|
-
i0.ɵɵelementStart(4, "span",
|
|
982
|
+
i0.ɵɵelementStart(4, "span", 179);
|
|
1061
983
|
i0.ɵɵtext(5);
|
|
1062
984
|
i0.ɵɵpipe(6, "slice");
|
|
1063
985
|
i0.ɵɵelementEnd()()();
|
|
1064
986
|
} if (rf & 2) {
|
|
1065
|
-
const
|
|
1066
|
-
i0.ɵɵproperty("mjClickable",
|
|
987
|
+
const notification_r56 = ctx.$implicit;
|
|
988
|
+
i0.ɵɵproperty("mjClickable", notification_r56.Title);
|
|
1067
989
|
i0.ɵɵadvance(3);
|
|
1068
|
-
i0.ɵɵtextInterpolate(
|
|
990
|
+
i0.ɵɵtextInterpolate(notification_r56.Title);
|
|
1069
991
|
i0.ɵɵadvance(2);
|
|
1070
|
-
i0.ɵɵtextInterpolate2("", i0.ɵɵpipeBind3(6, 4,
|
|
992
|
+
i0.ɵɵtextInterpolate2("", i0.ɵɵpipeBind3(6, 4, notification_r56.Message, 0, 40), "", ((notification_r56.Message == null ? null : notification_r56.Message.length) || 0) > 40 ? "..." : "");
|
|
1071
993
|
} }
|
|
1072
|
-
function
|
|
1073
|
-
i0.ɵɵelementStart(0, "div",
|
|
1074
|
-
i0.ɵɵelement(2, "i",
|
|
994
|
+
function HomeDashboardComponent_Conditional_12_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
995
|
+
i0.ɵɵelementStart(0, "div", 167)(1, "h4", 171);
|
|
996
|
+
i0.ɵɵelement(2, "i", 172);
|
|
1075
997
|
i0.ɵɵtext(3, " Notifications ");
|
|
1076
|
-
i0.ɵɵelementStart(4, "span",
|
|
998
|
+
i0.ɵɵelementStart(4, "span", 173);
|
|
1077
999
|
i0.ɵɵtext(5);
|
|
1078
1000
|
i0.ɵɵelementEnd()();
|
|
1079
|
-
i0.ɵɵelementStart(6, "div",
|
|
1080
|
-
i0.ɵɵrepeaterCreate(7,
|
|
1001
|
+
i0.ɵɵelementStart(6, "div", 174);
|
|
1002
|
+
i0.ɵɵrepeaterCreate(7, HomeDashboardComponent_Conditional_12_Conditional_8_For_8_Template, 7, 8, "div", 175, i0.ɵɵcomponentInstance().trackByNotification, true);
|
|
1081
1003
|
i0.ɵɵelementEnd()();
|
|
1082
1004
|
} if (rf & 2) {
|
|
1083
1005
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
@@ -1086,53 +1008,53 @@ function HomeDashboardComponent_Conditional_15_Conditional_8_Template(rf, ctx) {
|
|
|
1086
1008
|
i0.ɵɵadvance(2);
|
|
1087
1009
|
i0.ɵɵrepeater(ctx_r2.unreadNotifications);
|
|
1088
1010
|
} }
|
|
1089
|
-
function
|
|
1090
|
-
const
|
|
1091
|
-
i0.ɵɵelementStart(0, "div",
|
|
1092
|
-
i0.ɵɵlistener("click", function
|
|
1093
|
-
i0.ɵɵelementStart(1, "div",
|
|
1011
|
+
function HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1012
|
+
const _r57 = i0.ɵɵgetCurrentView();
|
|
1013
|
+
i0.ɵɵelementStart(0, "div", 183);
|
|
1014
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_4_For_2_Template_div_click_0_listener() { const favorite_r58 = i0.ɵɵrestoreView(_r57).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.onFavoriteClick(favorite_r58)); });
|
|
1015
|
+
i0.ɵɵelementStart(1, "div", 184);
|
|
1094
1016
|
i0.ɵɵelement(2, "i");
|
|
1095
1017
|
i0.ɵɵelementEnd();
|
|
1096
|
-
i0.ɵɵelementStart(3, "div",
|
|
1018
|
+
i0.ɵɵelementStart(3, "div", 177)(4, "span", 178);
|
|
1097
1019
|
i0.ɵɵtext(5);
|
|
1098
1020
|
i0.ɵɵelementEnd();
|
|
1099
|
-
i0.ɵɵelementStart(6, "span",
|
|
1021
|
+
i0.ɵɵelementStart(6, "span", 179);
|
|
1100
1022
|
i0.ɵɵtext(7);
|
|
1101
1023
|
i0.ɵɵelementEnd()()();
|
|
1102
1024
|
} if (rf & 2) {
|
|
1103
|
-
const
|
|
1025
|
+
const favorite_r58 = ctx.$implicit;
|
|
1104
1026
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
1105
|
-
i0.ɵɵproperty("mjClickable", ctx_r2.getFavoriteDisplayName(
|
|
1027
|
+
i0.ɵɵproperty("mjClickable", ctx_r2.getFavoriteDisplayName(favorite_r58));
|
|
1106
1028
|
i0.ɵɵadvance(2);
|
|
1107
|
-
i0.ɵɵclassMap(ctx_r2.getEntityIconByName(
|
|
1029
|
+
i0.ɵɵclassMap(ctx_r2.getEntityIconByName(favorite_r58.Entity));
|
|
1108
1030
|
i0.ɵɵadvance(3);
|
|
1109
|
-
i0.ɵɵtextInterpolate(ctx_r2.getFavoriteDisplayName(
|
|
1031
|
+
i0.ɵɵtextInterpolate(ctx_r2.getFavoriteDisplayName(favorite_r58));
|
|
1110
1032
|
i0.ɵɵadvance(2);
|
|
1111
|
-
i0.ɵɵtextInterpolate(
|
|
1033
|
+
i0.ɵɵtextInterpolate(favorite_r58.Entity);
|
|
1112
1034
|
} }
|
|
1113
|
-
function
|
|
1114
|
-
i0.ɵɵelementStart(0, "div",
|
|
1115
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1035
|
+
function HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1036
|
+
i0.ɵɵelementStart(0, "div", 174);
|
|
1037
|
+
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_4_For_2_Template, 8, 5, "div", 182, i0.ɵɵcomponentInstance().trackByFavorite, true);
|
|
1116
1038
|
i0.ɵɵelementEnd();
|
|
1117
1039
|
} if (rf & 2) {
|
|
1118
1040
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
1119
1041
|
i0.ɵɵadvance();
|
|
1120
1042
|
i0.ɵɵrepeater(ctx_r2.favorites);
|
|
1121
1043
|
} }
|
|
1122
|
-
function
|
|
1123
|
-
i0.ɵɵelementStart(0, "div",
|
|
1124
|
-
i0.ɵɵelement(1, "i",
|
|
1044
|
+
function HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1045
|
+
i0.ɵɵelementStart(0, "div", 181);
|
|
1046
|
+
i0.ɵɵelement(1, "i", 185);
|
|
1125
1047
|
i0.ɵɵelementStart(2, "span");
|
|
1126
1048
|
i0.ɵɵtext(3, "Loading...");
|
|
1127
1049
|
i0.ɵɵelementEnd()();
|
|
1128
1050
|
} }
|
|
1129
|
-
function
|
|
1130
|
-
i0.ɵɵelementStart(0, "div",
|
|
1131
|
-
i0.ɵɵelement(2, "i",
|
|
1051
|
+
function HomeDashboardComponent_Conditional_12_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
1052
|
+
i0.ɵɵelementStart(0, "div", 168)(1, "h4", 171);
|
|
1053
|
+
i0.ɵɵelement(2, "i", 180);
|
|
1132
1054
|
i0.ɵɵtext(3, " Favorites ");
|
|
1133
1055
|
i0.ɵɵelementEnd();
|
|
1134
|
-
i0.ɵɵconditionalCreate(4,
|
|
1135
|
-
i0.ɵɵconditionalCreate(5,
|
|
1056
|
+
i0.ɵɵconditionalCreate(4, HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_4_Template, 3, 0, "div", 174);
|
|
1057
|
+
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_12_Conditional_9_Conditional_5_Template, 4, 0, "div", 181);
|
|
1136
1058
|
i0.ɵɵelementEnd();
|
|
1137
1059
|
} if (rf & 2) {
|
|
1138
1060
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
@@ -1141,53 +1063,53 @@ function HomeDashboardComponent_Conditional_15_Conditional_9_Template(rf, ctx) {
|
|
|
1141
1063
|
i0.ɵɵadvance();
|
|
1142
1064
|
i0.ɵɵconditional(ctx_r2.favoritesLoading ? 5 : -1);
|
|
1143
1065
|
} }
|
|
1144
|
-
function
|
|
1145
|
-
const
|
|
1146
|
-
i0.ɵɵelementStart(0, "div",
|
|
1147
|
-
i0.ɵɵlistener("click", function
|
|
1148
|
-
i0.ɵɵelementStart(1, "div",
|
|
1066
|
+
function HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
1067
|
+
const _r59 = i0.ɵɵgetCurrentView();
|
|
1068
|
+
i0.ɵɵelementStart(0, "div", 188);
|
|
1069
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_4_For_2_Template_div_click_0_listener() { const item_r60 = i0.ɵɵrestoreView(_r59).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.onRecentClick(item_r60)); });
|
|
1070
|
+
i0.ɵɵelementStart(1, "div", 184);
|
|
1149
1071
|
i0.ɵɵelement(2, "i");
|
|
1150
1072
|
i0.ɵɵelementEnd();
|
|
1151
|
-
i0.ɵɵelementStart(3, "div",
|
|
1073
|
+
i0.ɵɵelementStart(3, "div", 177)(4, "span", 178);
|
|
1152
1074
|
i0.ɵɵtext(5);
|
|
1153
1075
|
i0.ɵɵelementEnd();
|
|
1154
|
-
i0.ɵɵelementStart(6, "span",
|
|
1076
|
+
i0.ɵɵelementStart(6, "span", 179);
|
|
1155
1077
|
i0.ɵɵtext(7);
|
|
1156
1078
|
i0.ɵɵelementEnd()()();
|
|
1157
1079
|
} if (rf & 2) {
|
|
1158
|
-
const
|
|
1080
|
+
const item_r60 = ctx.$implicit;
|
|
1159
1081
|
const ctx_r2 = i0.ɵɵnextContext(4);
|
|
1160
|
-
i0.ɵɵproperty("mjClickable",
|
|
1082
|
+
i0.ɵɵproperty("mjClickable", item_r60.recordName || item_r60.recordId);
|
|
1161
1083
|
i0.ɵɵadvance(2);
|
|
1162
|
-
i0.ɵɵclassMap(ctx_r2.getEntityIconByName(
|
|
1084
|
+
i0.ɵɵclassMap(ctx_r2.getEntityIconByName(item_r60.entityName));
|
|
1163
1085
|
i0.ɵɵadvance(3);
|
|
1164
|
-
i0.ɵɵtextInterpolate(
|
|
1086
|
+
i0.ɵɵtextInterpolate(item_r60.recordName || item_r60.recordId);
|
|
1165
1087
|
i0.ɵɵadvance(2);
|
|
1166
|
-
i0.ɵɵtextInterpolate2("",
|
|
1088
|
+
i0.ɵɵtextInterpolate2("", item_r60.entityName, " \u00B7 ", ctx_r2.formatDate(item_r60.latestAt));
|
|
1167
1089
|
} }
|
|
1168
|
-
function
|
|
1169
|
-
i0.ɵɵelementStart(0, "div",
|
|
1170
|
-
i0.ɵɵrepeaterCreate(1,
|
|
1090
|
+
function HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
1091
|
+
i0.ɵɵelementStart(0, "div", 174);
|
|
1092
|
+
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_4_For_2_Template, 8, 6, "div", 187, i0.ɵɵcomponentInstance().trackByRecent, true);
|
|
1171
1093
|
i0.ɵɵelementEnd();
|
|
1172
1094
|
} if (rf & 2) {
|
|
1173
1095
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
1174
1096
|
i0.ɵɵadvance();
|
|
1175
1097
|
i0.ɵɵrepeater(ctx_r2.recentItems);
|
|
1176
1098
|
} }
|
|
1177
|
-
function
|
|
1178
|
-
i0.ɵɵelementStart(0, "div",
|
|
1179
|
-
i0.ɵɵelement(1, "i",
|
|
1099
|
+
function HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
1100
|
+
i0.ɵɵelementStart(0, "div", 181);
|
|
1101
|
+
i0.ɵɵelement(1, "i", 185);
|
|
1180
1102
|
i0.ɵɵelementStart(2, "span");
|
|
1181
1103
|
i0.ɵɵtext(3, "Loading...");
|
|
1182
1104
|
i0.ɵɵelementEnd()();
|
|
1183
1105
|
} }
|
|
1184
|
-
function
|
|
1185
|
-
i0.ɵɵelementStart(0, "div",
|
|
1186
|
-
i0.ɵɵelement(2, "i",
|
|
1106
|
+
function HomeDashboardComponent_Conditional_12_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
1107
|
+
i0.ɵɵelementStart(0, "div", 169)(1, "h4", 171);
|
|
1108
|
+
i0.ɵɵelement(2, "i", 186);
|
|
1187
1109
|
i0.ɵɵtext(3, " Recent ");
|
|
1188
1110
|
i0.ɵɵelementEnd();
|
|
1189
|
-
i0.ɵɵconditionalCreate(4,
|
|
1190
|
-
i0.ɵɵconditionalCreate(5,
|
|
1111
|
+
i0.ɵɵconditionalCreate(4, HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_4_Template, 3, 0, "div", 174);
|
|
1112
|
+
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_12_Conditional_10_Conditional_5_Template, 4, 0, "div", 181);
|
|
1191
1113
|
i0.ɵɵelementEnd();
|
|
1192
1114
|
} if (rf & 2) {
|
|
1193
1115
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
@@ -1196,24 +1118,24 @@ function HomeDashboardComponent_Conditional_15_Conditional_10_Template(rf, ctx)
|
|
|
1196
1118
|
i0.ɵɵadvance();
|
|
1197
1119
|
i0.ɵɵconditional(ctx_r2.recentsLoading ? 5 : -1);
|
|
1198
1120
|
} }
|
|
1199
|
-
function
|
|
1200
|
-
i0.ɵɵelement(0, "mj-empty-state",
|
|
1121
|
+
function HomeDashboardComponent_Conditional_12_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
1122
|
+
i0.ɵɵelement(0, "mj-empty-state", 170);
|
|
1201
1123
|
} }
|
|
1202
|
-
function
|
|
1203
|
-
const
|
|
1204
|
-
i0.ɵɵelementStart(0, "div",
|
|
1205
|
-
i0.ɵɵelement(3, "i",
|
|
1124
|
+
function HomeDashboardComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
1125
|
+
const _r54 = i0.ɵɵgetCurrentView();
|
|
1126
|
+
i0.ɵɵelementStart(0, "div", 13)(1, "div", 164)(2, "h3");
|
|
1127
|
+
i0.ɵɵelement(3, "i", 160);
|
|
1206
1128
|
i0.ɵɵtext(4, " Quick Access ");
|
|
1207
1129
|
i0.ɵɵelementEnd();
|
|
1208
|
-
i0.ɵɵelementStart(5, "button",
|
|
1209
|
-
i0.ɵɵlistener("click", function
|
|
1210
|
-
i0.ɵɵelement(6, "i",
|
|
1130
|
+
i0.ɵɵelementStart(5, "button", 165);
|
|
1131
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_12_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r54); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleSidebar()); });
|
|
1132
|
+
i0.ɵɵelement(6, "i", 52);
|
|
1211
1133
|
i0.ɵɵelementEnd()();
|
|
1212
|
-
i0.ɵɵelementStart(7, "div",
|
|
1213
|
-
i0.ɵɵconditionalCreate(8,
|
|
1214
|
-
i0.ɵɵconditionalCreate(9,
|
|
1215
|
-
i0.ɵɵconditionalCreate(10,
|
|
1216
|
-
i0.ɵɵconditionalCreate(11,
|
|
1134
|
+
i0.ɵɵelementStart(7, "div", 166);
|
|
1135
|
+
i0.ɵɵconditionalCreate(8, HomeDashboardComponent_Conditional_12_Conditional_8_Template, 9, 1, "div", 167);
|
|
1136
|
+
i0.ɵɵconditionalCreate(9, HomeDashboardComponent_Conditional_12_Conditional_9_Template, 6, 2, "div", 168);
|
|
1137
|
+
i0.ɵɵconditionalCreate(10, HomeDashboardComponent_Conditional_12_Conditional_10_Template, 6, 2, "div", 169);
|
|
1138
|
+
i0.ɵɵconditionalCreate(11, HomeDashboardComponent_Conditional_12_Conditional_11_Template, 1, 0, "mj-empty-state", 170);
|
|
1217
1139
|
i0.ɵɵelementEnd()();
|
|
1218
1140
|
} if (rf & 2) {
|
|
1219
1141
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -1226,8 +1148,8 @@ function HomeDashboardComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
|
1226
1148
|
i0.ɵɵadvance();
|
|
1227
1149
|
i0.ɵɵconditional(!ctx_r2.favoritesLoading && !ctx_r2.recentsLoading && ctx_r2.unreadNotifications.length === 0 && ctx_r2.favorites.length === 0 && ctx_r2.recentItems.length === 0 ? 11 : -1);
|
|
1228
1150
|
} }
|
|
1229
|
-
function
|
|
1230
|
-
i0.ɵɵelementStart(0, "span",
|
|
1151
|
+
function HomeDashboardComponent_Conditional_13_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
1152
|
+
i0.ɵɵelementStart(0, "span", 190);
|
|
1231
1153
|
i0.ɵɵtext(1);
|
|
1232
1154
|
i0.ɵɵelementEnd();
|
|
1233
1155
|
} if (rf & 2) {
|
|
@@ -1235,18 +1157,32 @@ function HomeDashboardComponent_Conditional_16_Conditional_2_Template(rf, ctx) {
|
|
|
1235
1157
|
i0.ɵɵadvance();
|
|
1236
1158
|
i0.ɵɵtextInterpolate(ctx_r2.unreadNotifications.length);
|
|
1237
1159
|
} }
|
|
1238
|
-
function
|
|
1239
|
-
const
|
|
1240
|
-
i0.ɵɵelementStart(0, "button",
|
|
1241
|
-
i0.ɵɵlistener("click", function
|
|
1242
|
-
i0.ɵɵelement(1, "i",
|
|
1243
|
-
i0.ɵɵconditionalCreate(2,
|
|
1160
|
+
function HomeDashboardComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
1161
|
+
const _r61 = i0.ɵɵgetCurrentView();
|
|
1162
|
+
i0.ɵɵelementStart(0, "button", 189);
|
|
1163
|
+
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_13_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r61); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleSidebar()); });
|
|
1164
|
+
i0.ɵɵelement(1, "i", 160);
|
|
1165
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_13_Conditional_2_Template, 2, 1, "span", 190);
|
|
1244
1166
|
i0.ɵɵelementEnd();
|
|
1245
1167
|
} if (rf & 2) {
|
|
1246
1168
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
1247
1169
|
i0.ɵɵadvance(2);
|
|
1248
1170
|
i0.ɵɵconditional(ctx_r2.unreadNotifications.length > 0 ? 2 : -1);
|
|
1249
1171
|
} }
|
|
1172
|
+
/** User setting for the Pinned section: 'true' when collapsed, 'false' when open. A missing setting means open. */
|
|
1173
|
+
const PINNED_COLLAPSED_SETTING = 'HomeApp.PinnedCollapsed';
|
|
1174
|
+
/** The query param that names the dashboard Home shows in place of its overview. */
|
|
1175
|
+
const DASHBOARD_QUERY_PARAM = 'dashboard';
|
|
1176
|
+
/** The dashboard view's title: the switcher button that names the open dashboard. */
|
|
1177
|
+
const DASHBOARD_TITLE_SELECTOR = '.dashboard-title .switcher-title';
|
|
1178
|
+
/** The notice when Home cannot show the dashboard the URL or the editor names. */
|
|
1179
|
+
const DASHBOARD_NOT_AVAILABLE = 'That dashboard is not available';
|
|
1180
|
+
/** The name the SwitchHomeDashboard agent tool takes for Home's overview (any letter case). */
|
|
1181
|
+
const HOME_OVERVIEW_NAME = 'Home';
|
|
1182
|
+
/** Width of the pin options menu, in pixels. */
|
|
1183
|
+
const PIN_MENU_WIDTH = 220;
|
|
1184
|
+
/** Process-wide counter for the ids that label each Home's pin menu groups. */
|
|
1185
|
+
let nextPinMenuUid = 0;
|
|
1250
1186
|
/**
|
|
1251
1187
|
* Home Dashboard - Personalized home screen showing all available applications
|
|
1252
1188
|
* with quick access navigation and configuration options.
|
|
@@ -1262,7 +1198,11 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1262
1198
|
destroy$ = new Subject();
|
|
1263
1199
|
metadata = this.ProviderToUse;
|
|
1264
1200
|
pinService = inject(HomeAppPinService);
|
|
1201
|
+
confirmService = inject(MJConfirmService);
|
|
1202
|
+
hostElement = inject(ElementRef);
|
|
1265
1203
|
AppConfigDialog;
|
|
1204
|
+
pinMenuEl;
|
|
1205
|
+
dashboardEditor;
|
|
1266
1206
|
/** @deprecated Use {@link AppConfigDialog}. */
|
|
1267
1207
|
get appConfigDialog() {
|
|
1268
1208
|
return this.AppConfigDialog;
|
|
@@ -1272,6 +1212,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1272
1212
|
this.AppConfigDialog = value;
|
|
1273
1213
|
}
|
|
1274
1214
|
// State
|
|
1215
|
+
/** True until Home's first load finishes; the page shows its loading view meanwhile. A later app-list reload does not set it. */
|
|
1275
1216
|
isLoading = true;
|
|
1276
1217
|
Apps = [];
|
|
1277
1218
|
/** @deprecated Use {@link Apps}. */
|
|
@@ -1378,10 +1319,14 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1378
1319
|
}
|
|
1379
1320
|
// Pin empty-state dismissal preference (persisted in UserSettings via UserInfoEngine)
|
|
1380
1321
|
HidePinEmptyState = false;
|
|
1322
|
+
/** Whether the Pinned section is open. Saved for each user in the HomeApp.PinnedCollapsed setting. */
|
|
1323
|
+
PinnedExpanded = true;
|
|
1381
1324
|
// Pin state
|
|
1382
1325
|
PinnedItems = [];
|
|
1383
1326
|
UngroupedPins = [];
|
|
1384
1327
|
PinGroups = [];
|
|
1328
|
+
/** The pin grid's runs: ungrouped pins first, then each group in group order. */
|
|
1329
|
+
PinSections = [];
|
|
1385
1330
|
EditMode = false;
|
|
1386
1331
|
AddPanelOpen = false;
|
|
1387
1332
|
AddPanelSearchQuery = '';
|
|
@@ -1409,9 +1354,50 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1409
1354
|
PinMenuVisible = false;
|
|
1410
1355
|
PinMenuX = 0;
|
|
1411
1356
|
PinMenuY = 0;
|
|
1357
|
+
/** The pin menu's max height in pixels: the room on its side of the button. Null while the menu is measured. */
|
|
1358
|
+
PinMenuMaxHeight = null;
|
|
1412
1359
|
PinMenuPin = null;
|
|
1413
|
-
|
|
1360
|
+
/** Id of the menu's "Move to Group" header, which names the group rows. */
|
|
1361
|
+
PinMenuGroupLabelId = `home-pin-menu-groups-${nextPinMenuUid++}`;
|
|
1362
|
+
/** The ellipsis button that opened the pin options menu. Escape and Tab put focus back on it. */
|
|
1363
|
+
pinMenuTrigger = null;
|
|
1364
|
+
// Whether the Add Pin panel found the Data Explorer app. Query pins then open in its Queries nav item.
|
|
1414
1365
|
HasDataExplorerApp = false;
|
|
1366
|
+
// Dashboard view: a pinned dashboard shown in place of the overview
|
|
1367
|
+
/** The dashboard Home shows in place of its overview, or null on the overview. */
|
|
1368
|
+
CurrentDashboard = null;
|
|
1369
|
+
/** ID of that dashboard, or null. */
|
|
1370
|
+
CurrentDashboardId = null;
|
|
1371
|
+
/** True when the dashboard view opens in edit mode. The editor reads it once, then sets it back to false. */
|
|
1372
|
+
DashboardStartsInEditMode = false;
|
|
1373
|
+
/** True while the dashboard Home shows is in edit mode. */
|
|
1374
|
+
IsDashboardEditing = false;
|
|
1375
|
+
/** The pinned Config dashboards, in pin order, for the Dashboards switcher. */
|
|
1376
|
+
PinnedDashboards = [];
|
|
1377
|
+
/** The names dashboard pins show, by pin id: their dashboards' names from the dashboard cache. */
|
|
1378
|
+
pinDashboardNames = new Map();
|
|
1379
|
+
/** True once the first load of the dashboard cache has finished, also when it failed. */
|
|
1380
|
+
dashboardCacheLoaded = false;
|
|
1381
|
+
/** The dashboard the URL asks for; shown once the dashboard cache has loaded. */
|
|
1382
|
+
requestedDashboardId = null;
|
|
1383
|
+
/**
|
|
1384
|
+
* The dashboard Home shows because a URL change named it: back, forward or a deep link into the open tab. When the
|
|
1385
|
+
* editor cannot show it, Home leaves the URL as it is. Home's first load does not set it, and any other change of the
|
|
1386
|
+
* shown dashboard clears it.
|
|
1387
|
+
*/
|
|
1388
|
+
urlShownDashboardId = null;
|
|
1389
|
+
/**
|
|
1390
|
+
* The dashboard whose title gets focus when the editor has shown it: one the user picked in a switcher or opened from a
|
|
1391
|
+
* pin, or one an agent showed after its switch removed the part of Home that had focus.
|
|
1392
|
+
*/
|
|
1393
|
+
focusTitleOnLoad = null;
|
|
1394
|
+
// New dashboard: the name dialog
|
|
1395
|
+
/** True while the New dashboard name dialog is open. */
|
|
1396
|
+
ShowNewDashboardDialog = false;
|
|
1397
|
+
/** True while the named dashboard is being created. */
|
|
1398
|
+
IsCreatingDashboard = false;
|
|
1399
|
+
/** The longest name the dialog accepts. */
|
|
1400
|
+
NewDashboardNameMaxLength = DASHBOARD_NAME_MAX_LENGTH;
|
|
1415
1401
|
// Drag state
|
|
1416
1402
|
DraggingPinId = null;
|
|
1417
1403
|
DragOverPinId = null;
|
|
@@ -1428,6 +1414,26 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1428
1414
|
set favoriteDisplayNames(value) {
|
|
1429
1415
|
this.FavoriteDisplayNames = value;
|
|
1430
1416
|
}
|
|
1417
|
+
/** True when Home shows its overview: the greeting, Pinned and My applications. */
|
|
1418
|
+
get ShowOverview() {
|
|
1419
|
+
return !this.isLoading && !this.CurrentDashboard;
|
|
1420
|
+
}
|
|
1421
|
+
/** True when Home shows a dashboard in place of its overview. */
|
|
1422
|
+
get ShowDashboardView() {
|
|
1423
|
+
return !this.isLoading && this.CurrentDashboard !== null;
|
|
1424
|
+
}
|
|
1425
|
+
/** The Quick Access button and sidebar show on the overview only: in the dashboard view the button would cover the header's actions. */
|
|
1426
|
+
get ShowQuickAccess() {
|
|
1427
|
+
return this.HasSidebarContent && !this.CurrentDashboard;
|
|
1428
|
+
}
|
|
1429
|
+
/** The name of the dashboard Home shows, from the dashboard cache; null on the overview. */
|
|
1430
|
+
get CurrentDashboardName() {
|
|
1431
|
+
return this.CurrentDashboardId ? this.cachedDashboardName(this.CurrentDashboardId) : null;
|
|
1432
|
+
}
|
|
1433
|
+
/** True while the dashboard Home shows is in edit mode (see BaseResourceComponent.IsEditing). */
|
|
1434
|
+
IsEditing() {
|
|
1435
|
+
return this.IsDashboardEditing;
|
|
1436
|
+
}
|
|
1431
1437
|
/**
|
|
1432
1438
|
* Check if sidebar has any content to show
|
|
1433
1439
|
*/
|
|
@@ -1443,10 +1449,12 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1443
1449
|
return this.HasSidebarContent;
|
|
1444
1450
|
}
|
|
1445
1451
|
/**
|
|
1446
|
-
*
|
|
1452
|
+
* Opens or closes the Quick Access sidebar and marks Home for check, so the change shows at the next render also
|
|
1453
|
+
* when the agent's ToggleSidebar tool calls this outside a template event.
|
|
1447
1454
|
*/
|
|
1448
1455
|
ToggleSidebar() {
|
|
1449
1456
|
this.SidebarOpen = !this.SidebarOpen;
|
|
1457
|
+
this.cdr.markForCheck();
|
|
1450
1458
|
}
|
|
1451
1459
|
/** @deprecated Use {@link ToggleSidebar}. */
|
|
1452
1460
|
toggleSidebar() {
|
|
@@ -1474,20 +1482,20 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1474
1482
|
// Get current user info
|
|
1475
1483
|
this.CurrentUser = {
|
|
1476
1484
|
Name: this.metadata.CurrentUser?.Name || 'User',
|
|
1477
|
-
Email: this.metadata.CurrentUser?.Email || ''
|
|
1485
|
+
Email: this.metadata.CurrentUser?.Email || '',
|
|
1486
|
+
FirstName: this.metadata.CurrentUser?.FirstName || ''
|
|
1478
1487
|
};
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
// Subscribe to applications list, filtering out the Home app
|
|
1488
|
+
this.loadSectionStates();
|
|
1489
|
+
// The dashboard the tab's data names, for when the query-param stream has not delivered one
|
|
1490
|
+
const initialDashboard = this.GetQueryParams()[DASHBOARD_QUERY_PARAM]?.trim();
|
|
1491
|
+
if (initialDashboard && !this.requestedDashboardId) {
|
|
1492
|
+
this.requestedDashboardId = initialDashboard;
|
|
1493
|
+
}
|
|
1494
|
+
// The Dashboards part of the first load: the automatic app install and the dashboard cache
|
|
1495
|
+
const dashboardsLoad = this.loadDashboards();
|
|
1496
|
+
// Subscribe to applications list, filtering out the Home app. The loading view shows during the first load
|
|
1497
|
+
// only: a later reload of the list (an app install) keeps the page as it is, so an open dashboard and its edit
|
|
1498
|
+
// stay, and the overview keeps its apps until the new list arrives.
|
|
1491
1499
|
this.appManager.Applications
|
|
1492
1500
|
.pipe(takeUntil(this.destroy$))
|
|
1493
1501
|
.subscribe(async (apps) => {
|
|
@@ -1495,6 +1503,8 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1495
1503
|
this.Apps = apps.filter(app => app.Name !== 'Home');
|
|
1496
1504
|
// Pre-compute display data for all apps
|
|
1497
1505
|
await this.computeAppsDisplayData();
|
|
1506
|
+
// The page shows once the Dashboards part of the first load is done (see loadDashboards)
|
|
1507
|
+
await dashboardsLoad;
|
|
1498
1508
|
this.isLoading = false;
|
|
1499
1509
|
this.NotifyLoadComplete();
|
|
1500
1510
|
// Apps changed → keep the agent's view of the launcher in sync.
|
|
@@ -1519,6 +1529,10 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1519
1529
|
this.publishAgentContext();
|
|
1520
1530
|
this.cdr.markForCheck();
|
|
1521
1531
|
});
|
|
1532
|
+
// The switcher, the dashboard pin names and the open dashboard follow changes to the dashboard cache
|
|
1533
|
+
ObserveDashboardLibraryChanges()
|
|
1534
|
+
.pipe(takeUntil(this.destroy$))
|
|
1535
|
+
.subscribe(() => this.refreshPinnedDashboards());
|
|
1522
1536
|
// Favorites and recents load asynchronously in the sidebar
|
|
1523
1537
|
this.NotifyLoadComplete();
|
|
1524
1538
|
// Load favorites and recents asynchronously (don't block rendering)
|
|
@@ -1535,8 +1549,11 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1535
1549
|
this.PinnedItems = pins;
|
|
1536
1550
|
this.UngroupedPins = this.pinService.GetUngroupedPins();
|
|
1537
1551
|
this.PinGroups = this.pinService.GetGroups();
|
|
1538
|
-
this.
|
|
1539
|
-
|
|
1552
|
+
this.PinSections = [
|
|
1553
|
+
{ Key: 'ungrouped', Group: null, Pins: this.UngroupedPins },
|
|
1554
|
+
...this.PinGroups.map(group => ({ Key: `group:${group}`, Group: group, Pins: this.pinService.GetPinsInGroup(group) })),
|
|
1555
|
+
];
|
|
1556
|
+
this.refreshPinnedDashboards();
|
|
1540
1557
|
});
|
|
1541
1558
|
// Resolve display names for record-type pins that have raw ID titles
|
|
1542
1559
|
this.resolveRecordPinNames();
|
|
@@ -1562,11 +1579,16 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1562
1579
|
//
|
|
1563
1580
|
// 🚨 SAFETY BOUNDARY: the Home dashboard exposes ONLY navigation / discovery /
|
|
1564
1581
|
// panel-toggle operations to the agent. No pin create, no pin delete, no pin
|
|
1565
|
-
// rename, no group mutation, no reordering
|
|
1566
|
-
//
|
|
1567
|
-
//
|
|
1568
|
-
//
|
|
1569
|
-
//
|
|
1582
|
+
// rename, no group mutation, no reordering, and no dashboard create, rename,
|
|
1583
|
+
// edit, save or delete — those are user-confirm-driven or destructive and stay
|
|
1584
|
+
// in the UI. Home registers no dashboard edit tools for the dashboard it shows
|
|
1585
|
+
// (those are on the dashboard tab). Every tool below maps to the exact same
|
|
1586
|
+
// component method a user click would call (OpenApp→OnAppClick, OpenPin→openPin,
|
|
1587
|
+
// which a pin click calls, SwitchHomeDashboard→OpenDashboardInHome / GoHome,
|
|
1588
|
+
// which a switcher pick calls, search→AddPanel search field, panel/sidebar/
|
|
1589
|
+
// edit-mode toggles). Leaving a dashboard with unsaved changes asks the user
|
|
1590
|
+
// first, as it does for a click. Handlers are tolerant: they never throw,
|
|
1591
|
+
// returning { Success, Data?, ErrorMessage? }.
|
|
1570
1592
|
/**
|
|
1571
1593
|
* Publish the current Home dashboard state to the AI agent via NavigationService.
|
|
1572
1594
|
* The shaping lives in the pure {@link buildHomeAgentContext} helper so it stays
|
|
@@ -1580,7 +1602,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1580
1602
|
PinnedItemCount: this.PinnedItems.length,
|
|
1581
1603
|
PinGroupCount: this.PinGroups.length,
|
|
1582
1604
|
PinGroupNames: this.PinGroups,
|
|
1583
|
-
PinNames: this.PinnedItems.map(p => p
|
|
1605
|
+
PinNames: this.PinnedItems.map(p => this.PinName(p)),
|
|
1584
1606
|
UnreadNotifications: this.UnreadNotifications.length,
|
|
1585
1607
|
NotificationTitles: this.UnreadNotifications.map(n => n.Title ?? '(untitled)'),
|
|
1586
1608
|
RecentItemsCount: this.RecentItems.length,
|
|
@@ -1589,6 +1611,11 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1589
1611
|
AddPanelOpen: this.AddPanelOpen,
|
|
1590
1612
|
SidebarOpen: this.SidebarOpen,
|
|
1591
1613
|
AddPanelSearchQuery: this.AddPanelSearchQuery,
|
|
1614
|
+
PinnedCollapsed: !this.PinnedExpanded,
|
|
1615
|
+
CurrentDashboardName: this.CurrentDashboardName,
|
|
1616
|
+
CurrentDashboardID: this.CurrentDashboardId,
|
|
1617
|
+
IsEditingDashboard: this.IsDashboardEditing,
|
|
1618
|
+
PinnedDashboardNames: this.PinnedDashboards.map(d => d.Name),
|
|
1592
1619
|
});
|
|
1593
1620
|
this.navigationService.SetAgentContext(this, context);
|
|
1594
1621
|
}
|
|
@@ -1607,14 +1634,16 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1607
1634
|
*
|
|
1608
1635
|
* Tools:
|
|
1609
1636
|
* - OpenApp: switch to an application by name (exact or partial match).
|
|
1610
|
-
* - OpenPin: open a pinned item by
|
|
1637
|
+
* - OpenPin: open a pinned item by the name it shows (exact or partial match). A pinned dashboard opens inside Home.
|
|
1611
1638
|
* - SearchPins: find pinned items by a name query (read-only — returns matches).
|
|
1612
1639
|
* - OpenRecent: open a recently-accessed item by display name (read-only navigation).
|
|
1613
1640
|
* - SearchAddPinPanel: open the Add Pin panel (if needed) and apply a search query.
|
|
1614
1641
|
* - ClearAddPinPanelSearch: clear the Add Pin panel search query.
|
|
1615
1642
|
* - OpenAddPinPanel / CloseAddPinPanel: toggle the Add Pin panel.
|
|
1616
|
-
* - ToggleSidebar: toggle the notifications/favorites/recents sidebar.
|
|
1617
|
-
* - TogglePinEditMode: toggle pin edit mode (reorder/rename UI affordances).
|
|
1643
|
+
* - ToggleSidebar: toggle the notifications/favorites/recents sidebar (on the overview only).
|
|
1644
|
+
* - TogglePinEditMode: toggle pin edit mode (reorder/rename UI affordances; on the overview only).
|
|
1645
|
+
* - SwitchHomeDashboard: show a pinned dashboard inside Home by its name (exact or partial match) or id, or "Home"
|
|
1646
|
+
* for the overview.
|
|
1618
1647
|
*/
|
|
1619
1648
|
registerAgentClientTools() {
|
|
1620
1649
|
this.navigationService.SetAgentClientTools(this, [
|
|
@@ -1626,13 +1655,13 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1626
1655
|
},
|
|
1627
1656
|
{
|
|
1628
1657
|
Name: 'OpenPin',
|
|
1629
|
-
Description: 'Open a pinned item on the Home screen by
|
|
1658
|
+
Description: 'Open a pinned item on the Home screen by the name it shows (exact or partial match). A pinned dashboard opens inside Home; other pins open as before.',
|
|
1630
1659
|
ParameterSchema: { type: 'object', properties: { pinName: { type: 'string' } }, required: ['pinName'] },
|
|
1631
1660
|
Handler: async (params) => this.toolOpenPin(params),
|
|
1632
1661
|
},
|
|
1633
1662
|
{
|
|
1634
1663
|
Name: 'SearchPins',
|
|
1635
|
-
Description: 'Find pinned items on the Home screen whose
|
|
1664
|
+
Description: 'Find pinned items on the Home screen whose name, as the pin shows it, matches a query (case-insensitive contains). Read-only — returns the matching pin names; does not open anything.',
|
|
1636
1665
|
ParameterSchema: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] },
|
|
1637
1666
|
Handler: async (params) => this.toolSearchPins(params),
|
|
1638
1667
|
},
|
|
@@ -1676,23 +1705,21 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1676
1705
|
},
|
|
1677
1706
|
{
|
|
1678
1707
|
Name: 'ToggleSidebar',
|
|
1679
|
-
Description:
|
|
1708
|
+
Description: `Toggle the Home sidebar (unread notifications, favorites, and recent items). Quick Access shows on the ${HOME_OVERVIEW_NAME} overview only: while Home shows a dashboard, use SwitchHomeDashboard with "${HOME_OVERVIEW_NAME}" first.`,
|
|
1680
1709
|
ParameterSchema: { type: 'object', properties: {} },
|
|
1681
|
-
Handler: async () =>
|
|
1682
|
-
this.ToggleSidebar();
|
|
1683
|
-
this.publishAgentContext();
|
|
1684
|
-
return { Success: true, Data: { SidebarOpen: this.SidebarOpen } };
|
|
1685
|
-
},
|
|
1710
|
+
Handler: async () => this.toolToggleSidebar(),
|
|
1686
1711
|
},
|
|
1687
1712
|
{
|
|
1688
1713
|
Name: 'TogglePinEditMode',
|
|
1689
|
-
Description:
|
|
1714
|
+
Description: `Toggle pin edit mode on the Home overview (lets the user rename/reorder pins). This only changes the UI mode — it does not modify any pins. Pin edit mode shows on the ${HOME_OVERVIEW_NAME} overview only: while Home shows a dashboard, use SwitchHomeDashboard with "${HOME_OVERVIEW_NAME}" first.`,
|
|
1690
1715
|
ParameterSchema: { type: 'object', properties: {} },
|
|
1691
|
-
Handler: async () =>
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
},
|
|
1716
|
+
Handler: async () => this.toolTogglePinEditMode(),
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
Name: 'SwitchHomeDashboard',
|
|
1720
|
+
Description: `Show a pinned dashboard inside Home by its name (exact or partial match) or id, or "${HOME_OVERVIEW_NAME}" to return to the Home overview. Navigation only — it does not pin, unpin, rename or edit dashboards. When the open dashboard has unsaved changes, the user is asked first.`,
|
|
1721
|
+
ParameterSchema: { type: 'object', properties: { dashboard: { type: 'string' } }, required: ['dashboard'] },
|
|
1722
|
+
Handler: async (params) => this.toolSwitchHomeDashboard(params),
|
|
1696
1723
|
},
|
|
1697
1724
|
]);
|
|
1698
1725
|
}
|
|
@@ -1718,12 +1745,15 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1718
1745
|
await this.OnAppClick(app);
|
|
1719
1746
|
return { Success: true, Data: { AppName: app.Name } };
|
|
1720
1747
|
}
|
|
1721
|
-
/** The pinned items
|
|
1748
|
+
/** The pinned items with the names they show, for the resolver. */
|
|
1722
1749
|
get pinNamedRecords() {
|
|
1723
|
-
return this.PinnedItems.map(
|
|
1750
|
+
return this.PinnedItems.map(pin => ({ Name: this.PinName(pin), Pin: pin }));
|
|
1724
1751
|
}
|
|
1725
|
-
/**
|
|
1726
|
-
|
|
1752
|
+
/**
|
|
1753
|
+
* Resolve a pinned item by the name it shows (exact then partial, case-insensitive) and open it. A pinned dashboard
|
|
1754
|
+
* opens inside Home. Focus stays where it is unless the change removed it (see refocusIfRemoved).
|
|
1755
|
+
*/
|
|
1756
|
+
async toolOpenPin(params) {
|
|
1727
1757
|
const parsed = ValidateStringParam(params['pinName'], 'pinName');
|
|
1728
1758
|
if (!parsed.ok) {
|
|
1729
1759
|
return parsed.result;
|
|
@@ -1732,32 +1762,35 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1732
1762
|
if (!pinName) {
|
|
1733
1763
|
return { Success: false, ErrorMessage: 'pinName is required.' };
|
|
1734
1764
|
}
|
|
1735
|
-
const
|
|
1765
|
+
const records = this.pinNamedRecords;
|
|
1766
|
+
const match = ResolveNamedRecord(pinName, records);
|
|
1736
1767
|
if (!match) {
|
|
1737
|
-
return { Success: false, ErrorMessage: BuildHomeNotFoundError(pinName, 'pinned item',
|
|
1768
|
+
return { Success: false, ErrorMessage: BuildHomeNotFoundError(pinName, 'pinned item', records) };
|
|
1738
1769
|
}
|
|
1739
|
-
const
|
|
1740
|
-
if (!
|
|
1741
|
-
return { Success: false, ErrorMessage:
|
|
1770
|
+
const opened = await this.switchViewForAgent(() => this.leaveEditModeAndOpenPin(match.Pin));
|
|
1771
|
+
if (!opened) {
|
|
1772
|
+
return { Success: false, ErrorMessage: `"${match.Name}" did not open. The pin may be broken, or the user kept editing the open dashboard.` };
|
|
1742
1773
|
}
|
|
1743
|
-
|
|
1774
|
+
return { Success: true, Data: { PinName: match.Name } };
|
|
1775
|
+
}
|
|
1776
|
+
/** Opens a pin for the agent. A pin does not open in edit mode: Home leaves it first, as Done does, and tells the agent. */
|
|
1777
|
+
leaveEditModeAndOpenPin(pin) {
|
|
1744
1778
|
if (this.EditMode) {
|
|
1745
|
-
this.
|
|
1779
|
+
this.ToggleEditMode();
|
|
1780
|
+
this.publishAgentContext();
|
|
1746
1781
|
}
|
|
1747
|
-
this.
|
|
1748
|
-
return { Success: true, Data: { PinName: pin.DisplayName } };
|
|
1782
|
+
return this.openPin(pin);
|
|
1749
1783
|
}
|
|
1750
|
-
/** Find pinned items whose
|
|
1784
|
+
/** Find pinned items whose shown name matches a query (read-only — returns matches). */
|
|
1751
1785
|
toolSearchPins(params) {
|
|
1752
1786
|
const parsed = ValidateStringParam(params['query'], 'query');
|
|
1753
1787
|
if (!parsed.ok) {
|
|
1754
1788
|
return parsed.result;
|
|
1755
1789
|
}
|
|
1756
1790
|
const query = parsed.value.trim().toLowerCase();
|
|
1757
|
-
const
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
return { Success: true, Data: { Matches: matches.map(p => p.DisplayName), MatchCount: matches.length } };
|
|
1791
|
+
const names = this.PinnedItems.map(p => this.PinName(p));
|
|
1792
|
+
const matches = query ? names.filter(name => name.toLowerCase().includes(query)) : names;
|
|
1793
|
+
return { Success: true, Data: { Matches: matches, MatchCount: matches.length } };
|
|
1761
1794
|
}
|
|
1762
1795
|
/** Resolve a recent item by display name (exact then partial) and navigate to it. */
|
|
1763
1796
|
toolOpenRecent(params) {
|
|
@@ -1785,6 +1818,60 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1785
1818
|
this.OnRecentClick(item);
|
|
1786
1819
|
return { Success: true, Data: { Name: match.Name, ResourceType: item.resourceType } };
|
|
1787
1820
|
}
|
|
1821
|
+
/**
|
|
1822
|
+
* Shows a pinned dashboard in Home by id (any letter case) or name (exact, then partial), or the overview for
|
|
1823
|
+
* "Home". It uses the methods a switcher pick uses, so the user is asked first about unsaved changes. Unlike a pick,
|
|
1824
|
+
* it moves focus only when the switch removed it (see refocusIfRemoved).
|
|
1825
|
+
*/
|
|
1826
|
+
async toolSwitchHomeDashboard(params) {
|
|
1827
|
+
const parsed = ValidateStringParam(params['dashboard'], 'dashboard');
|
|
1828
|
+
if (!parsed.ok) {
|
|
1829
|
+
return parsed.result;
|
|
1830
|
+
}
|
|
1831
|
+
const reference = parsed.value.trim();
|
|
1832
|
+
if (!reference) {
|
|
1833
|
+
return { Success: false, ErrorMessage: 'dashboard is required.' };
|
|
1834
|
+
}
|
|
1835
|
+
if (reference.toLowerCase() === HOME_OVERVIEW_NAME.toLowerCase()) {
|
|
1836
|
+
return (await this.switchViewForAgent(() => this.GoHome()))
|
|
1837
|
+
? { Success: true, Data: { HomeView: 'Overview' } }
|
|
1838
|
+
: { Success: false, ErrorMessage: `The ${HOME_OVERVIEW_NAME} overview did not open. The user kept editing the open dashboard.` };
|
|
1839
|
+
}
|
|
1840
|
+
const target = ResolvePinnedDashboardReference(reference, this.PinnedDashboards);
|
|
1841
|
+
if (!target) {
|
|
1842
|
+
const candidates = [{ Name: HOME_OVERVIEW_NAME }, ...this.PinnedDashboards.map(d => ({ Name: d.Name }))];
|
|
1843
|
+
return { Success: false, ErrorMessage: BuildHomeNotFoundError(reference, 'pinned dashboard', candidates) };
|
|
1844
|
+
}
|
|
1845
|
+
// The switcher's list can trail the dashboard cache by a moment
|
|
1846
|
+
if (!this.findHomeDashboard(target.ID)) {
|
|
1847
|
+
return { Success: false, ErrorMessage: `"${target.Name}" did not open. The dashboard is not available.` };
|
|
1848
|
+
}
|
|
1849
|
+
if (!(await this.switchViewForAgent(() => this.OpenDashboardInHome(target.ID)))) {
|
|
1850
|
+
return { Success: false, ErrorMessage: `"${target.Name}" did not open. The user kept editing the open dashboard.` };
|
|
1851
|
+
}
|
|
1852
|
+
return { Success: true, Data: { CurrentDashboardName: target.Name } };
|
|
1853
|
+
}
|
|
1854
|
+
/** Opens or closes Quick Access. While a dashboard shows, where Quick Access does not show, it changes nothing. */
|
|
1855
|
+
toolToggleSidebar() {
|
|
1856
|
+
if (this.CurrentDashboardId) {
|
|
1857
|
+
return { Success: false, ErrorMessage: overviewOnlyError('Quick Access') };
|
|
1858
|
+
}
|
|
1859
|
+
this.ToggleSidebar();
|
|
1860
|
+
this.publishAgentContext();
|
|
1861
|
+
return { Success: true, Data: { SidebarOpen: this.SidebarOpen } };
|
|
1862
|
+
}
|
|
1863
|
+
/**
|
|
1864
|
+
* Turns pin edit mode on or off. While a dashboard shows, where the pins do not show, it changes nothing: it neither
|
|
1865
|
+
* opens a collapsed Pinned section nor saves that.
|
|
1866
|
+
*/
|
|
1867
|
+
toolTogglePinEditMode() {
|
|
1868
|
+
if (this.CurrentDashboardId) {
|
|
1869
|
+
return { Success: false, ErrorMessage: overviewOnlyError('Pin edit mode') };
|
|
1870
|
+
}
|
|
1871
|
+
this.ToggleEditMode();
|
|
1872
|
+
this.publishAgentContext();
|
|
1873
|
+
return { Success: true, Data: { EditMode: this.EditMode } };
|
|
1874
|
+
}
|
|
1788
1875
|
/** Open the Add Pin panel (if needed) and apply a search query. */
|
|
1789
1876
|
async toolSearchAddPinPanel(params) {
|
|
1790
1877
|
const parsed = ValidateStringParam(params['query'], 'query');
|
|
@@ -1826,6 +1913,10 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1826
1913
|
get greeting() {
|
|
1827
1914
|
return this.Greeting;
|
|
1828
1915
|
}
|
|
1916
|
+
/** The first name the greeting uses, or the user's display name. */
|
|
1917
|
+
get GreetingName() {
|
|
1918
|
+
return this.CurrentUser?.FirstName || this.CurrentUser?.Name || 'User';
|
|
1919
|
+
}
|
|
1829
1920
|
/**
|
|
1830
1921
|
* Get formatted date string
|
|
1831
1922
|
*/
|
|
@@ -1889,7 +1980,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
1889
1980
|
}));
|
|
1890
1981
|
return {
|
|
1891
1982
|
app,
|
|
1892
|
-
color: app.GetColor() || '
|
|
1983
|
+
color: app.GetColor() || 'var(--mj-brand-primary)',
|
|
1893
1984
|
icon: app.Icon || 'fa-solid fa-cube',
|
|
1894
1985
|
navItemsCount,
|
|
1895
1986
|
navItemsPreview,
|
|
@@ -2019,10 +2110,10 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2019
2110
|
// Navigate based on entity type using NavigationService
|
|
2020
2111
|
const entityName = favorite.Entity?.toLowerCase();
|
|
2021
2112
|
const recordId = favorite.RecordID;
|
|
2022
|
-
if (
|
|
2023
|
-
this.
|
|
2113
|
+
if (IsDashboardEntity(favorite.Entity)) {
|
|
2114
|
+
this.openDashboard(recordId, 'Dashboard');
|
|
2024
2115
|
}
|
|
2025
|
-
else if (
|
|
2116
|
+
else if (ResourceTypeForEntity(favorite.Entity) === 'view') {
|
|
2026
2117
|
this.navigationService.OpenView(recordId, 'View');
|
|
2027
2118
|
}
|
|
2028
2119
|
else if (entityName?.includes('artifact')) {
|
|
@@ -2051,7 +2142,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2051
2142
|
this.navigationService.OpenView(item.recordId, name || 'View');
|
|
2052
2143
|
break;
|
|
2053
2144
|
case 'dashboard':
|
|
2054
|
-
this.
|
|
2145
|
+
this.openDashboard(item.recordId, name || 'Dashboard');
|
|
2055
2146
|
break;
|
|
2056
2147
|
case 'artifact':
|
|
2057
2148
|
this.navigationService.OpenArtifact(item.recordId, name || 'Artifact');
|
|
@@ -2065,118 +2156,534 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2065
2156
|
}
|
|
2066
2157
|
}
|
|
2067
2158
|
}
|
|
2068
|
-
/** @deprecated Use {@link OnRecentClick}. */
|
|
2069
|
-
onRecentClick(item) {
|
|
2070
|
-
return this.OnRecentClick(item);
|
|
2159
|
+
/** @deprecated Use {@link OnRecentClick}. */
|
|
2160
|
+
onRecentClick(item) {
|
|
2161
|
+
return this.OnRecentClick(item);
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Navigate to a notification using NavigationService
|
|
2165
|
+
*/
|
|
2166
|
+
OnNotificationClick(notification) {
|
|
2167
|
+
// Navigate to the notifications view using NavigationService
|
|
2168
|
+
this.navigationService.OpenDynamicView('MJ: User Notifications');
|
|
2169
|
+
}
|
|
2170
|
+
/** @deprecated Use {@link OnNotificationClick}. */
|
|
2171
|
+
onNotificationClick(notification) {
|
|
2172
|
+
return this.OnNotificationClick(notification);
|
|
2173
|
+
}
|
|
2174
|
+
/**
|
|
2175
|
+
* Get icon for an entity by name, using entity metadata Icon field (cached)
|
|
2176
|
+
*/
|
|
2177
|
+
GetEntityIconByName(entityName) {
|
|
2178
|
+
if (!entityName)
|
|
2179
|
+
return 'fa-solid fa-file';
|
|
2180
|
+
const cached = this.resourceIconCache.get(entityName);
|
|
2181
|
+
if (cached)
|
|
2182
|
+
return cached;
|
|
2183
|
+
const entityInfo = this.metadata.Entities.find(e => e.Name === entityName);
|
|
2184
|
+
const icon = entityInfo ? this.resolveEntityIcon(entityInfo.Icon) : 'fa-solid fa-file';
|
|
2185
|
+
this.resourceIconCache.set(entityName, icon);
|
|
2186
|
+
return icon;
|
|
2187
|
+
}
|
|
2188
|
+
/** @deprecated Use {@link GetEntityIconByName}. */
|
|
2189
|
+
getEntityIconByName(entityName) {
|
|
2190
|
+
return this.GetEntityIconByName(entityName);
|
|
2191
|
+
}
|
|
2192
|
+
/**
|
|
2193
|
+
* Resolve an entity's Icon field to a full Font Awesome class string
|
|
2194
|
+
*/
|
|
2195
|
+
resolveEntityIcon(icon) {
|
|
2196
|
+
if (!icon)
|
|
2197
|
+
return 'fa-solid fa-table';
|
|
2198
|
+
// Already has a style prefix
|
|
2199
|
+
if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||
|
|
2200
|
+
icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||
|
|
2201
|
+
icon.startsWith('fa ')) {
|
|
2202
|
+
return icon;
|
|
2203
|
+
}
|
|
2204
|
+
// Has fa- prefix but no style
|
|
2205
|
+
if (icon.startsWith('fa-')) {
|
|
2206
|
+
return `fa-solid ${icon}`;
|
|
2207
|
+
}
|
|
2208
|
+
// Just an icon name like "table" or "users"
|
|
2209
|
+
return `fa-solid fa-${icon}`;
|
|
2210
|
+
}
|
|
2211
|
+
/**
|
|
2212
|
+
* Format a date for display (pure function, safe to call in template)
|
|
2213
|
+
*/
|
|
2214
|
+
formatDate(date) {
|
|
2215
|
+
if (!date)
|
|
2216
|
+
return '';
|
|
2217
|
+
const now = new Date();
|
|
2218
|
+
const diff = now.getTime() - new Date(date).getTime();
|
|
2219
|
+
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
2220
|
+
if (days === 0)
|
|
2221
|
+
return 'Today';
|
|
2222
|
+
if (days === 1)
|
|
2223
|
+
return 'Yesterday';
|
|
2224
|
+
if (days < 7)
|
|
2225
|
+
return `${days} days ago`;
|
|
2226
|
+
return new Date(date).toLocaleDateString();
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Track function for favorites
|
|
2230
|
+
*/
|
|
2231
|
+
TrackByFavorite(_index, item) {
|
|
2232
|
+
return item.ID;
|
|
2233
|
+
}
|
|
2234
|
+
/** @deprecated Use {@link TrackByFavorite}. */
|
|
2235
|
+
trackByFavorite(_index, item) {
|
|
2236
|
+
return this.TrackByFavorite(_index, item);
|
|
2237
|
+
}
|
|
2238
|
+
/**
|
|
2239
|
+
* Remove duplicate recent items (same entity + recordId). Keeps the first occurrence.
|
|
2240
|
+
*/
|
|
2241
|
+
deduplicateRecents(items) {
|
|
2242
|
+
const seen = new Set();
|
|
2243
|
+
return items.filter(item => {
|
|
2244
|
+
const key = `${item.entityName}-${item.recordId}`;
|
|
2245
|
+
if (seen.has(key)) {
|
|
2246
|
+
return false;
|
|
2247
|
+
}
|
|
2248
|
+
seen.add(key);
|
|
2249
|
+
return true;
|
|
2250
|
+
});
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Track function for recent items
|
|
2254
|
+
*/
|
|
2255
|
+
TrackByRecent(_index, item) {
|
|
2256
|
+
return `${item.entityName}-${item.recordId}`;
|
|
2257
|
+
}
|
|
2258
|
+
/** @deprecated Use {@link TrackByRecent}. */
|
|
2259
|
+
trackByRecent(_index, item) {
|
|
2260
|
+
return this.TrackByRecent(_index, item);
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Track function for notifications
|
|
2264
|
+
*/
|
|
2265
|
+
TrackByNotification(_index, item) {
|
|
2266
|
+
return item.ID;
|
|
2267
|
+
}
|
|
2268
|
+
/** @deprecated Use {@link TrackByNotification}. */
|
|
2269
|
+
trackByNotification(_index, item) {
|
|
2270
|
+
return this.TrackByNotification(_index, item);
|
|
2271
|
+
}
|
|
2272
|
+
// =============================================
|
|
2273
|
+
// DASHBOARDS APP AND CACHE
|
|
2274
|
+
// =============================================
|
|
2275
|
+
/**
|
|
2276
|
+
* The Dashboards part of Home's first load: the automatic Dashboards app install (at most once
|
|
2277
|
+
* per user) and the dashboard cache. Home stays on its loading view until both finish, so the
|
|
2278
|
+
* app-list reload that an install causes does not show a second loading view. Each install step
|
|
2279
|
+
* gives up after DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS. The cache load has no time limit: Home
|
|
2280
|
+
* shows its loading view until the server answers or the load fails. Never rejects.
|
|
2281
|
+
*/
|
|
2282
|
+
async loadDashboards() {
|
|
2283
|
+
await Promise.allSettled([AutoInstallDashboardsApp(this.appManager), this.loadDashboardCache()]);
|
|
2284
|
+
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Loads the dashboard cache if it is not loaded yet, then reads the switcher's list and the dashboard pin names
|
|
2287
|
+
* from it and shows the dashboard the URL asks for (one Home cannot show is removed from the URL). A failed load is
|
|
2288
|
+
* only logged. Never rejects.
|
|
2289
|
+
*/
|
|
2290
|
+
async loadDashboardCache() {
|
|
2291
|
+
try {
|
|
2292
|
+
await DashboardEngine.Instance.Config(false, this.ProviderToUse.CurrentUser, this.ProviderToUse);
|
|
2293
|
+
}
|
|
2294
|
+
catch (error) {
|
|
2295
|
+
LogError(`Home: could not load the dashboards: ${errorMessage(error)}`);
|
|
2296
|
+
}
|
|
2297
|
+
this.dashboardCacheLoaded = true;
|
|
2298
|
+
this.refreshPinnedDashboards();
|
|
2299
|
+
this.applyRequestedDashboard(true);
|
|
2300
|
+
}
|
|
2301
|
+
/** Reloads the dashboard cache, so a dashboard saved a moment ago is in it. A failure is only logged. */
|
|
2302
|
+
async reloadDashboardCache() {
|
|
2303
|
+
try {
|
|
2304
|
+
await DashboardEngine.Instance.Config(true, this.ProviderToUse.CurrentUser, this.ProviderToUse);
|
|
2305
|
+
}
|
|
2306
|
+
catch (error) {
|
|
2307
|
+
LogError(`Home: could not reload the dashboards: ${errorMessage(error)}`);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
/** The dashboards the user can open, from the dashboard cache; none when the user cannot read the cache. */
|
|
2311
|
+
accessibleDashboards() {
|
|
2312
|
+
const engine = DashboardEngine.Instance;
|
|
2313
|
+
return engine.IsPermissionConstrained ? [] : engine.GetAccessibleDashboards(this.ProviderToUse.CurrentUser.ID);
|
|
2314
|
+
}
|
|
2315
|
+
/** Re-reads the switcher's list and the names dashboard pins show, and keeps the open dashboard in step with the cache. */
|
|
2316
|
+
refreshPinnedDashboards() {
|
|
2317
|
+
const dashboards = this.accessibleDashboards();
|
|
2318
|
+
this.PinnedDashboards = BuildPinnedDashboards(this.PinnedItems, dashboards);
|
|
2319
|
+
this.pinDashboardNames = BuildPinDashboardNames(this.PinnedItems, dashboards);
|
|
2320
|
+
this.syncCurrentDashboard(dashboards);
|
|
2321
|
+
this.publishAgentContext();
|
|
2322
|
+
this.cdr.markForCheck();
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Opens a dashboard in place of the preview tab, which is usually the tab that shows Home, so Back
|
|
2326
|
+
* returns to Home. A Shift-click opens it in a separate tab.
|
|
2327
|
+
*/
|
|
2328
|
+
openDashboard(dashboardId, dashboardName) {
|
|
2329
|
+
this.navigationService.OpenDashboard(dashboardId, dashboardName);
|
|
2330
|
+
}
|
|
2331
|
+
/**
|
|
2332
|
+
* Follows a link from a panel of the dashboard Home shows: a record, a dashboard or a query, as the
|
|
2333
|
+
* dashboard tab does. Other link types are only logged.
|
|
2334
|
+
*/
|
|
2335
|
+
OnDashboardNavigationRequested(event) {
|
|
2336
|
+
const request = event.request;
|
|
2337
|
+
switch (request.type) {
|
|
2338
|
+
case 'OpenEntityRecord': {
|
|
2339
|
+
const key = CompositeKey.FromURLSegment(this.ProviderToUse.EntityByName(request.entityName), request.recordId);
|
|
2340
|
+
this.navigationService.OpenEntityRecord(request.entityName, key);
|
|
2341
|
+
break;
|
|
2342
|
+
}
|
|
2343
|
+
case 'OpenDashboard':
|
|
2344
|
+
this.openDashboard(request.dashboardId, this.cachedDashboardName(request.dashboardId));
|
|
2345
|
+
break;
|
|
2346
|
+
case 'OpenQuery':
|
|
2347
|
+
this.navigationService.OpenQuery(request.queryId, 'Query');
|
|
2348
|
+
break;
|
|
2349
|
+
default:
|
|
2350
|
+
console.warn(`[Home] A dashboard panel asked for a link type that Home does not open: ${request.type}`);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
/** The dashboard's name from the dashboard cache, or 'Dashboard' when the cache does not have it. */
|
|
2354
|
+
cachedDashboardName(dashboardId) {
|
|
2355
|
+
const engine = DashboardEngine.Instance;
|
|
2356
|
+
if (engine.IsPermissionConstrained) {
|
|
2357
|
+
return 'Dashboard';
|
|
2358
|
+
}
|
|
2359
|
+
return engine.Dashboards.find(d => UUIDsEqual(d.ID, dashboardId))?.Name ?? 'Dashboard';
|
|
2360
|
+
}
|
|
2361
|
+
// =============================================
|
|
2362
|
+
// DASHBOARD VIEW
|
|
2363
|
+
// =============================================
|
|
2364
|
+
/**
|
|
2365
|
+
* Shows a dashboard inside Home in place of the overview and writes it to the URL (?dashboard=<id>). Only a Config
|
|
2366
|
+
* dashboard the user can open shows in Home. Asks first when the open dashboard has unsaved changes. Returns false
|
|
2367
|
+
* when the dashboard did not open.
|
|
2368
|
+
*/
|
|
2369
|
+
async OpenDashboardInHome(dashboardId, startInEditMode = false) {
|
|
2370
|
+
const dashboard = this.findHomeDashboard(dashboardId);
|
|
2371
|
+
if (!dashboard)
|
|
2372
|
+
return false;
|
|
2373
|
+
if (UUIDsEqual(dashboard.ID, this.CurrentDashboardId))
|
|
2374
|
+
return true;
|
|
2375
|
+
if (!(await this.confirmLeaveDashboard()))
|
|
2376
|
+
return false;
|
|
2377
|
+
// Another open of the same dashboard (a double click) finished meanwhile
|
|
2378
|
+
if (UUIDsEqual(dashboard.ID, this.CurrentDashboardId))
|
|
2379
|
+
return true;
|
|
2380
|
+
this.requestedDashboardId = dashboard.ID;
|
|
2381
|
+
this.setCurrentDashboard(dashboard, startInEditMode);
|
|
2382
|
+
this.UpdateQueryParams({ [DASHBOARD_QUERY_PARAM]: dashboard.ID });
|
|
2383
|
+
void this.recentAccessService.LogAccess('MJ: Dashboards', dashboard.ID, 'dashboard');
|
|
2384
|
+
return true;
|
|
2385
|
+
}
|
|
2386
|
+
/**
|
|
2387
|
+
* Returns to the overview (switcher Home, breadcrumb Home) and removes the dashboard from the URL. Asks first when
|
|
2388
|
+
* the open dashboard has unsaved changes. Returns false when the user keeps editing.
|
|
2389
|
+
*/
|
|
2390
|
+
async GoHome() {
|
|
2391
|
+
if (!this.CurrentDashboardId)
|
|
2392
|
+
return true;
|
|
2393
|
+
if (!(await this.confirmLeaveDashboard()))
|
|
2394
|
+
return false;
|
|
2395
|
+
this.closeDashboardView();
|
|
2396
|
+
return true;
|
|
2397
|
+
}
|
|
2398
|
+
/**
|
|
2399
|
+
* A pick in a Dashboards switcher, or the breadcrumb's Home: null returns to the overview, an id opens that
|
|
2400
|
+
* dashboard in Home. Focus then moves to what shows.
|
|
2401
|
+
*/
|
|
2402
|
+
OnSwitcherPick(dashboardId) {
|
|
2403
|
+
void this.followSwitcherPick(dashboardId);
|
|
2404
|
+
}
|
|
2405
|
+
/**
|
|
2406
|
+
* Manage pins (switcher): the overview with the pins in edit mode, and focus on the Pinned header. When the user
|
|
2407
|
+
* keeps editing the open dashboard, Home stays on it and focus goes to its title.
|
|
2408
|
+
*/
|
|
2409
|
+
async ManagePins() {
|
|
2410
|
+
const home = await this.GoHome();
|
|
2411
|
+
if (home && !this.EditMode) {
|
|
2412
|
+
this.ToggleEditMode();
|
|
2413
|
+
}
|
|
2414
|
+
this.focusShownView();
|
|
2415
|
+
}
|
|
2416
|
+
/** The switcher's New dashboard: asks to leave unsaved changes first, then asks for the name. */
|
|
2417
|
+
async OpenNewDashboardDialog() {
|
|
2418
|
+
if (!(await this.confirmLeaveDashboard()))
|
|
2419
|
+
return;
|
|
2420
|
+
this.NewDashboardNameMaxLength = DashboardNameMaxLength(this.ProviderToUse);
|
|
2421
|
+
this.ShowNewDashboardDialog = true;
|
|
2422
|
+
this.cdr.markForCheck();
|
|
2423
|
+
}
|
|
2424
|
+
/** Closes the name dialog; nothing is created. */
|
|
2425
|
+
OnNewDashboardCancelled() {
|
|
2426
|
+
this.ShowNewDashboardDialog = false;
|
|
2427
|
+
this.cdr.markForCheck();
|
|
2428
|
+
}
|
|
2429
|
+
/**
|
|
2430
|
+
* Creates the named dashboard, pins it to Home and shows it in Home in edit mode. When the save fails, the
|
|
2431
|
+
* dialog stays open with the name and the user is told. A second Create while one runs is ignored.
|
|
2432
|
+
*/
|
|
2433
|
+
async OnNewDashboardNamed(name) {
|
|
2434
|
+
if (this.IsCreatingDashboard)
|
|
2435
|
+
return;
|
|
2436
|
+
this.IsCreatingDashboard = true;
|
|
2437
|
+
this.cdr.markForCheck();
|
|
2438
|
+
try {
|
|
2439
|
+
const dashboard = await CreateBlankDashboard(this.ProviderToUse, name);
|
|
2440
|
+
if (!dashboard) {
|
|
2441
|
+
MJNotificationService.Instance.CreateSimpleNotification('Could not create the dashboard', 'error', 3000);
|
|
2442
|
+
return;
|
|
2443
|
+
}
|
|
2444
|
+
await this.reloadDashboardCache();
|
|
2445
|
+
this.pinService.AddPin(BuildDashboardPinInput(dashboard));
|
|
2446
|
+
this.ShowNewDashboardDialog = false;
|
|
2447
|
+
if (!(await this.OpenDashboardInHome(dashboard.ID, true))) {
|
|
2448
|
+
this.openDashboard(dashboard.ID, dashboard.Name);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
catch (error) {
|
|
2452
|
+
LogError(`Home: could not open the new dashboard: ${errorMessage(error)}`);
|
|
2453
|
+
MJNotificationService.Instance.CreateSimpleNotification('Could not open the new dashboard', 'error', 3000);
|
|
2454
|
+
}
|
|
2455
|
+
finally {
|
|
2456
|
+
this.IsCreatingDashboard = false;
|
|
2457
|
+
this.cdr.markForCheck();
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
/** Opens the dashboard in a tab of the Dashboards app, installing the app first when the user lacks it. */
|
|
2461
|
+
async OpenDashboardInDashboardsApp(dashboard) {
|
|
2462
|
+
const app = await EnsureDashboardsApp(this.appManager);
|
|
2463
|
+
this.navigationService.OpenDashboard(dashboard.ID, dashboard.Name, app ? { applicationId: app.ID } : undefined);
|
|
2071
2464
|
}
|
|
2072
2465
|
/**
|
|
2073
|
-
*
|
|
2466
|
+
* The editor entered or left edit mode. The editor can report leaving it while Home renders (it drops an edit when
|
|
2467
|
+
* it gets another dashboard), so this sets no state the template reads, and tells the agent after the render.
|
|
2074
2468
|
*/
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
this.
|
|
2078
|
-
}
|
|
2079
|
-
/** @deprecated Use {@link OnNotificationClick}. */
|
|
2080
|
-
onNotificationClick(notification) {
|
|
2081
|
-
return this.OnNotificationClick(notification);
|
|
2469
|
+
OnDashboardEditingChange(editing) {
|
|
2470
|
+
this.IsDashboardEditing = editing;
|
|
2471
|
+
queueMicrotask(() => this.publishAgentContext());
|
|
2082
2472
|
}
|
|
2083
2473
|
/**
|
|
2084
|
-
*
|
|
2474
|
+
* The editor saved the dashboard, or its saved name changed: the switcher and the pin names read the new name from
|
|
2475
|
+
* the cache.
|
|
2085
2476
|
*/
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
return icon;
|
|
2477
|
+
OnDashboardSaved() {
|
|
2478
|
+
this.refreshPinnedDashboards();
|
|
2479
|
+
}
|
|
2480
|
+
/** The editor has shown a dashboard. Its title gets focus when Home asked for that (see focusTitleOnLoad). */
|
|
2481
|
+
OnDashboardViewLoaded(dashboard) {
|
|
2482
|
+
if (this.focusTitleOnLoad && UUIDsEqual(dashboard.ID, this.focusTitleOnLoad)) {
|
|
2483
|
+
this.focusTitleOnLoad = null;
|
|
2484
|
+
this.focusInHome(DASHBOARD_TITLE_SELECTOR);
|
|
2485
|
+
}
|
|
2096
2486
|
}
|
|
2097
|
-
/**
|
|
2098
|
-
|
|
2099
|
-
|
|
2487
|
+
/**
|
|
2488
|
+
* The editor could not show the dashboard: Home returns to its overview and tells the user. A dashboard that a URL
|
|
2489
|
+
* change named stays in the URL, since a write would add a history entry that every later Back lands on again. Any
|
|
2490
|
+
* other dashboard is removed from the URL: one the user opened in Home, or the one Home opened with on its first load,
|
|
2491
|
+
* so the tab does not keep it.
|
|
2492
|
+
*/
|
|
2493
|
+
OnDashboardViewLoadFailed() {
|
|
2494
|
+
const namedByUrl = this.urlShownDashboardId !== null && UUIDsEqual(this.urlShownDashboardId, this.CurrentDashboardId);
|
|
2495
|
+
this.closeDashboardView(DASHBOARD_NOT_AVAILABLE, !namedByUrl);
|
|
2496
|
+
}
|
|
2497
|
+
/** Applies the dashboard the URL names, for back and forward, deep links and pins of Home. */
|
|
2498
|
+
OnQueryParamsChanged(params, _source) {
|
|
2499
|
+
const requested = params[DASHBOARD_QUERY_PARAM]?.trim() || null;
|
|
2500
|
+
if (UUIDsEqual(requested, this.requestedDashboardId))
|
|
2501
|
+
return;
|
|
2502
|
+
if (this.hasUnsavedDashboardChanges()) {
|
|
2503
|
+
void this.followDashboardParamAfterConfirm(requested);
|
|
2504
|
+
return;
|
|
2505
|
+
}
|
|
2506
|
+
this.requestedDashboardId = requested;
|
|
2507
|
+
this.applyRequestedDashboard(false);
|
|
2100
2508
|
}
|
|
2101
2509
|
/**
|
|
2102
|
-
*
|
|
2510
|
+
* Asks before a URL change leaves unsaved changes. When the user keeps editing, writes the open dashboard back to the
|
|
2511
|
+
* URL.
|
|
2103
2512
|
*/
|
|
2104
|
-
|
|
2105
|
-
if (!
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||
|
|
2109
|
-
icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||
|
|
2110
|
-
icon.startsWith('fa ')) {
|
|
2111
|
-
return icon;
|
|
2513
|
+
async followDashboardParamAfterConfirm(requested) {
|
|
2514
|
+
if (!(await this.confirmLeaveDashboard())) {
|
|
2515
|
+
this.UpdateQueryParams({ [DASHBOARD_QUERY_PARAM]: this.CurrentDashboardId });
|
|
2516
|
+
return;
|
|
2112
2517
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2518
|
+
this.requestedDashboardId = requested;
|
|
2519
|
+
this.applyRequestedDashboard(false);
|
|
2520
|
+
}
|
|
2521
|
+
/**
|
|
2522
|
+
* Shows the dashboard the URL asks for, once the dashboard cache has loaded: the dashboard view for a Config
|
|
2523
|
+
* dashboard the user can open, else the overview. For a dashboard Home cannot show, the user is told, and
|
|
2524
|
+
* `removeFromUrl` removes it from the URL. After a URL change (back, forward, a deep link into the open tab) the URL
|
|
2525
|
+
* stays as it is: a write then would add a history entry that every later Back lands on again. After a URL change,
|
|
2526
|
+
* Home also notes that the URL named the dashboard it shows (see OnDashboardViewLoadFailed).
|
|
2527
|
+
*/
|
|
2528
|
+
applyRequestedDashboard(removeFromUrl) {
|
|
2529
|
+
if (!this.dashboardCacheLoaded)
|
|
2530
|
+
return;
|
|
2531
|
+
const requested = this.requestedDashboardId;
|
|
2532
|
+
const dashboard = requested ? this.findHomeDashboard(requested) : null;
|
|
2533
|
+
if (requested && !dashboard) {
|
|
2534
|
+
this.closeDashboardView(DASHBOARD_NOT_AVAILABLE, removeFromUrl);
|
|
2535
|
+
return;
|
|
2116
2536
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2537
|
+
this.setCurrentDashboard(dashboard, false);
|
|
2538
|
+
this.urlShownDashboardId = removeFromUrl ? null : dashboard?.ID ?? null;
|
|
2119
2539
|
}
|
|
2120
2540
|
/**
|
|
2121
|
-
*
|
|
2541
|
+
* Keeps the open dashboard in step with the cache: one that is gone, or that the user can no longer open, returns
|
|
2542
|
+
* Home to the overview.
|
|
2122
2543
|
*/
|
|
2123
|
-
|
|
2124
|
-
if (!
|
|
2125
|
-
return
|
|
2126
|
-
|
|
2127
|
-
const diff = now.getTime() - new Date(date).getTime();
|
|
2128
|
-
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
2129
|
-
if (days === 0)
|
|
2130
|
-
return 'Today';
|
|
2131
|
-
if (days === 1)
|
|
2132
|
-
return 'Yesterday';
|
|
2133
|
-
if (days < 7)
|
|
2134
|
-
return `${days} days ago`;
|
|
2135
|
-
return new Date(date).toLocaleDateString();
|
|
2544
|
+
syncCurrentDashboard(dashboards) {
|
|
2545
|
+
if (!this.dashboardCacheLoaded || !this.CurrentDashboardId || FindDashboard(dashboards, this.CurrentDashboardId))
|
|
2546
|
+
return;
|
|
2547
|
+
this.closeDashboardView('The dashboard is no longer available');
|
|
2136
2548
|
}
|
|
2137
2549
|
/**
|
|
2138
|
-
*
|
|
2550
|
+
* Returns Home to its overview and, with a notice, tells the user. `removeFromUrl` also removes the dashboard from
|
|
2551
|
+
* the URL; that write runs after the current call stack, and only when no dashboard shows by then.
|
|
2139
2552
|
*/
|
|
2140
|
-
|
|
2141
|
-
|
|
2553
|
+
closeDashboardView(notice, removeFromUrl = true) {
|
|
2554
|
+
this.requestedDashboardId = null;
|
|
2555
|
+
this.setCurrentDashboard(null, false);
|
|
2556
|
+
if (removeFromUrl) {
|
|
2557
|
+
queueMicrotask(() => {
|
|
2558
|
+
if (!this.CurrentDashboardId) {
|
|
2559
|
+
this.UpdateQueryParams({ [DASHBOARD_QUERY_PARAM]: null });
|
|
2560
|
+
}
|
|
2561
|
+
});
|
|
2562
|
+
}
|
|
2563
|
+
if (notice) {
|
|
2564
|
+
MJNotificationService.Instance.CreateSimpleNotification(notice, 'warning', 3000);
|
|
2565
|
+
}
|
|
2142
2566
|
}
|
|
2143
|
-
/**
|
|
2144
|
-
|
|
2145
|
-
|
|
2567
|
+
/**
|
|
2568
|
+
* Shows `dashboard` (or the overview for null). Home keeps the object it was given for the same dashboard: the
|
|
2569
|
+
* editor follows the dashboard cache itself after a save, so a new copy of the same dashboard is not pushed to it.
|
|
2570
|
+
*/
|
|
2571
|
+
setCurrentDashboard(dashboard, startInEditMode) {
|
|
2572
|
+
if (UUIDsEqual(dashboard?.ID, this.CurrentDashboardId))
|
|
2573
|
+
return;
|
|
2574
|
+
this.CurrentDashboard = dashboard;
|
|
2575
|
+
this.CurrentDashboardId = dashboard?.ID ?? null;
|
|
2576
|
+
this.DashboardStartsInEditMode = dashboard !== null && startInEditMode;
|
|
2577
|
+
this.IsDashboardEditing = false;
|
|
2578
|
+
this.focusTitleOnLoad = null;
|
|
2579
|
+
this.urlShownDashboardId = null;
|
|
2580
|
+
this.EditingPinId = null;
|
|
2581
|
+
this.SidebarOpen = false;
|
|
2582
|
+
this.HidePinMenu();
|
|
2583
|
+
this.publishAgentContext();
|
|
2584
|
+
this.cdr.markForCheck();
|
|
2585
|
+
}
|
|
2586
|
+
/** A Config dashboard the user can open, by id (any letter case), or null. */
|
|
2587
|
+
findHomeDashboard(dashboardId) {
|
|
2588
|
+
const dashboard = FindDashboard(this.accessibleDashboards(), dashboardId);
|
|
2589
|
+
return dashboard && CanShowInHome(dashboard) ? dashboard : null;
|
|
2590
|
+
}
|
|
2591
|
+
/** True while the open dashboard is in edit mode with changes the editor has not saved. */
|
|
2592
|
+
hasUnsavedDashboardChanges() {
|
|
2593
|
+
return this.IsDashboardEditing && (this.dashboardEditor?.HasUnsavedChanges ?? false);
|
|
2146
2594
|
}
|
|
2147
2595
|
/**
|
|
2148
|
-
*
|
|
2596
|
+
* True when Home may leave the open dashboard: it is not being edited, its changes are saved, or the user chose to
|
|
2597
|
+
* discard them (the editor then cancels its edit). False when the user keeps editing.
|
|
2149
2598
|
*/
|
|
2150
|
-
|
|
2151
|
-
const
|
|
2152
|
-
|
|
2153
|
-
const key = `${item.entityName}-${item.recordId}`;
|
|
2154
|
-
if (seen.has(key)) {
|
|
2155
|
-
return false;
|
|
2156
|
-
}
|
|
2157
|
-
seen.add(key);
|
|
2599
|
+
async confirmLeaveDashboard() {
|
|
2600
|
+
const editor = this.dashboardEditor;
|
|
2601
|
+
if (!editor || !this.IsDashboardEditing)
|
|
2158
2602
|
return true;
|
|
2603
|
+
if (editor.HasUnsavedChanges && !(await this.confirmDiscardDashboardChanges()))
|
|
2604
|
+
return false;
|
|
2605
|
+
editor.CancelEdit();
|
|
2606
|
+
return true;
|
|
2607
|
+
}
|
|
2608
|
+
/**
|
|
2609
|
+
* Asks whether to discard the open dashboard's unsaved changes. Resolves true for Discard changes, false for Keep
|
|
2610
|
+
* editing.
|
|
2611
|
+
*/
|
|
2612
|
+
confirmDiscardDashboardChanges() {
|
|
2613
|
+
return this.confirmService.Confirm({
|
|
2614
|
+
title: 'Discard changes?',
|
|
2615
|
+
message: `Leave "${this.CurrentDashboardName}" without saving?`,
|
|
2616
|
+
detail: 'Your changes to this dashboard will be lost.',
|
|
2617
|
+
type: 'warning',
|
|
2618
|
+
confirmText: 'Discard changes',
|
|
2619
|
+
cancelText: 'Keep editing',
|
|
2159
2620
|
});
|
|
2160
2621
|
}
|
|
2161
2622
|
/**
|
|
2162
|
-
*
|
|
2623
|
+
* Follows a switcher pick, then moves focus to what shows: a dashboard Home switched to gets focus on its title once
|
|
2624
|
+
* the editor has shown it; otherwise focus goes to the open dashboard's title, or to the Pinned header.
|
|
2163
2625
|
*/
|
|
2164
|
-
|
|
2165
|
-
|
|
2626
|
+
async followSwitcherPick(dashboardId) {
|
|
2627
|
+
const switching = dashboardId !== null && !UUIDsEqual(dashboardId, this.CurrentDashboardId);
|
|
2628
|
+
const moved = dashboardId ? await this.OpenDashboardInHome(dashboardId) : await this.GoHome();
|
|
2629
|
+
if (moved && switching) {
|
|
2630
|
+
this.focusTitleOnLoad = this.CurrentDashboardId;
|
|
2631
|
+
}
|
|
2632
|
+
else {
|
|
2633
|
+
this.focusShownView();
|
|
2634
|
+
}
|
|
2166
2635
|
}
|
|
2167
|
-
/**
|
|
2168
|
-
|
|
2169
|
-
|
|
2636
|
+
/** Runs an agent's change of Home's view, then moves focus when the change removed it (see refocusIfRemoved). */
|
|
2637
|
+
async switchViewForAgent(switchView) {
|
|
2638
|
+
const focused = this.focusedElementInHome();
|
|
2639
|
+
const switched = await switchView();
|
|
2640
|
+
this.refocusIfRemoved(focused);
|
|
2641
|
+
return switched;
|
|
2642
|
+
}
|
|
2643
|
+
/** The element in Home that has focus, or null when focus is outside Home. */
|
|
2644
|
+
focusedElementInHome() {
|
|
2645
|
+
const focused = document.activeElement;
|
|
2646
|
+
return focused instanceof HTMLElement && this.hostElement.nativeElement.contains(focused) ? focused : null;
|
|
2170
2647
|
}
|
|
2171
2648
|
/**
|
|
2172
|
-
*
|
|
2649
|
+
* After an agent changed Home's view: renders Home, and when `focused` is gone (the change removed the part of Home it
|
|
2650
|
+
* was in), moves focus as a switcher pick does, to the title of the dashboard Home shows once the editor has shown it,
|
|
2651
|
+
* or on the overview to the Pinned header. Focus that is still on the page stays where it is.
|
|
2173
2652
|
*/
|
|
2174
|
-
|
|
2175
|
-
|
|
2653
|
+
refocusIfRemoved(focused) {
|
|
2654
|
+
if (!focused)
|
|
2655
|
+
return;
|
|
2656
|
+
SafeDetectChanges(this.cdr);
|
|
2657
|
+
if (focused.isConnected)
|
|
2658
|
+
return;
|
|
2659
|
+
if (this.CurrentDashboardId) {
|
|
2660
|
+
this.focusTitleOnLoad = this.CurrentDashboardId;
|
|
2661
|
+
}
|
|
2662
|
+
else {
|
|
2663
|
+
this.focusShownView();
|
|
2664
|
+
}
|
|
2176
2665
|
}
|
|
2177
|
-
/**
|
|
2178
|
-
|
|
2179
|
-
|
|
2666
|
+
/**
|
|
2667
|
+
* Moves focus to the open dashboard's title, or on the overview to the Pinned header: its Dashboards button, or Done
|
|
2668
|
+
* while the pins are in edit mode.
|
|
2669
|
+
*/
|
|
2670
|
+
focusShownView() {
|
|
2671
|
+
if (this.CurrentDashboardId) {
|
|
2672
|
+
this.focusInHome(DASHBOARD_TITLE_SELECTOR);
|
|
2673
|
+
}
|
|
2674
|
+
else {
|
|
2675
|
+
this.focusInHome(this.EditMode ? '.pinned-actions > button' : '.pinned-actions .switcher-button');
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Renders Home, then focuses the first element in it that matches `selector`, and returns that element. Returns null,
|
|
2680
|
+
* and focuses nothing, when none shows.
|
|
2681
|
+
*/
|
|
2682
|
+
focusInHome(selector) {
|
|
2683
|
+
SafeDetectChanges(this.cdr);
|
|
2684
|
+
const element = this.hostElement.nativeElement.querySelector(selector);
|
|
2685
|
+
element?.focus();
|
|
2686
|
+
return element;
|
|
2180
2687
|
}
|
|
2181
2688
|
// =============================================
|
|
2182
2689
|
// PIN NAME RESOLUTION
|
|
@@ -2189,7 +2696,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2189
2696
|
// Find pins that need name resolution: records with raw ID titles,
|
|
2190
2697
|
// or any pin whose DisplayName contains "ID|" (raw composite key)
|
|
2191
2698
|
const pinsNeedingNames = this.PinnedItems.filter(pin => {
|
|
2192
|
-
const rt =
|
|
2699
|
+
const rt = ResolvePinResourceType(pin);
|
|
2193
2700
|
if (rt !== 'Records')
|
|
2194
2701
|
return false;
|
|
2195
2702
|
// Check if the name looks like a raw ID format
|
|
@@ -2232,7 +2739,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2232
2739
|
* Resolve missing icons for Custom (app nav item) pins by looking up nav items.
|
|
2233
2740
|
*/
|
|
2234
2741
|
async resolveCustomPinIcons() {
|
|
2235
|
-
const pinsNeedingIcons = this.PinnedItems.filter(pin =>
|
|
2742
|
+
const pinsNeedingIcons = this.PinnedItems.filter(pin => ResolvePinResourceType(pin) === 'Custom' && !pin.Icon);
|
|
2236
2743
|
if (pinsNeedingIcons.length === 0)
|
|
2237
2744
|
return;
|
|
2238
2745
|
for (const pin of pinsNeedingIcons) {
|
|
@@ -2254,145 +2761,144 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2254
2761
|
// PIN MANAGEMENT
|
|
2255
2762
|
// =============================================
|
|
2256
2763
|
/**
|
|
2257
|
-
*
|
|
2764
|
+
* Opens a pinned resource. A click in edit mode does nothing. A dashboard the click shows in Home gets focus on its
|
|
2765
|
+
* title once the editor has shown it.
|
|
2258
2766
|
*/
|
|
2259
2767
|
OnPinClick(pin) {
|
|
2768
|
+
void this.openPinForUser(pin);
|
|
2769
|
+
}
|
|
2770
|
+
/** Opens a pin the user clicked. When it shows a dashboard in Home, that dashboard's title gets focus once the editor has shown it. */
|
|
2771
|
+
async openPinForUser(pin) {
|
|
2772
|
+
const shown = this.CurrentDashboardId;
|
|
2773
|
+
if ((await this.openPin(pin)) && this.CurrentDashboardId && !UUIDsEqual(this.CurrentDashboardId, shown)) {
|
|
2774
|
+
this.focusTitleOnLoad = this.CurrentDashboardId;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Opens a pin: a dashboard pin as openDashboardPin describes, other pins as Home always has. Returns false when
|
|
2779
|
+
* nothing opened: in edit mode, for a broken pin, or when the user kept editing the open dashboard.
|
|
2780
|
+
*/
|
|
2781
|
+
async openPin(pin) {
|
|
2260
2782
|
if (this.EditMode)
|
|
2261
|
-
return;
|
|
2783
|
+
return false;
|
|
2784
|
+
const resourceType = ResolvePinResourceType(pin);
|
|
2785
|
+
return resourceType === 'Dashboards' ? this.openDashboardPin(pin) : this.openResourcePin(pin, resourceType);
|
|
2786
|
+
}
|
|
2787
|
+
/**
|
|
2788
|
+
* Opens a dashboard pin: a Config dashboard the user can open shows inside Home; a Code dashboard, or one the cache
|
|
2789
|
+
* does not have, opens in a tab under the name the pin shows. Returns false when nothing opened.
|
|
2790
|
+
*/
|
|
2791
|
+
async openDashboardPin(pin) {
|
|
2792
|
+
const dashboardId = DashboardIdOfPin(pin);
|
|
2793
|
+
if (!dashboardId) {
|
|
2794
|
+
console.warn('[Pin Click] Dashboards pin missing dashboardId and recordId', pin.Configuration);
|
|
2795
|
+
return false;
|
|
2796
|
+
}
|
|
2797
|
+
if (this.findHomeDashboard(dashboardId)) {
|
|
2798
|
+
return this.OpenDashboardInHome(dashboardId);
|
|
2799
|
+
}
|
|
2800
|
+
this.openDashboard(dashboardId, this.PinName(pin));
|
|
2801
|
+
return true;
|
|
2802
|
+
}
|
|
2803
|
+
/**
|
|
2804
|
+
* Opens a pin that is not a dashboard pin: a view, a query, a record, an app page or an action. Returns false when
|
|
2805
|
+
* the pin is broken and nothing opened.
|
|
2806
|
+
*/
|
|
2807
|
+
openResourcePin(pin, resourceType) {
|
|
2262
2808
|
const config = pin.Configuration;
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
const deApp = this.HasDataExplorerApp
|
|
2266
|
-
? this.appManager.GetAllApps().find(a => a.Name === 'Data Explorer')
|
|
2267
|
-
: null;
|
|
2268
|
-
switch (rt) {
|
|
2269
|
-
case 'Dashboards': {
|
|
2270
|
-
const dashboardId = config['dashboardId'];
|
|
2271
|
-
if (!dashboardId)
|
|
2272
|
-
break;
|
|
2273
|
-
if (deApp) {
|
|
2274
|
-
void this.navigationService.SwitchToApp(deApp.ID, 'Dashboards', { dashboard: dashboardId });
|
|
2275
|
-
}
|
|
2276
|
-
else {
|
|
2277
|
-
this.navigationService.OpenDashboard(dashboardId, pin.DisplayName);
|
|
2278
|
-
}
|
|
2279
|
-
break;
|
|
2280
|
-
}
|
|
2281
|
-
case 'User Views':
|
|
2809
|
+
switch (resourceType) {
|
|
2810
|
+
case 'User Views': {
|
|
2282
2811
|
if (config['isDynamic']) {
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
if (viewId) {
|
|
2288
|
-
this.navigationService.OpenView(viewId, pin.DisplayName);
|
|
2812
|
+
const entityName = (config['Entity'] || config['entity']);
|
|
2813
|
+
if (!entityName) {
|
|
2814
|
+
console.warn('[Pin Click] Dynamic view pin missing Entity', config);
|
|
2815
|
+
return false;
|
|
2289
2816
|
}
|
|
2817
|
+
this.navigationService.OpenDynamicView(entityName, config['extraFilter']);
|
|
2818
|
+
return true;
|
|
2290
2819
|
}
|
|
2291
|
-
|
|
2820
|
+
const viewId = config['viewId'];
|
|
2821
|
+
if (!viewId)
|
|
2822
|
+
return false;
|
|
2823
|
+
this.navigationService.OpenView(viewId, pin.DisplayName);
|
|
2824
|
+
return true;
|
|
2825
|
+
}
|
|
2292
2826
|
case 'Queries': {
|
|
2293
2827
|
const queryId = config['queryId'];
|
|
2294
2828
|
if (!queryId)
|
|
2295
|
-
|
|
2829
|
+
return false;
|
|
2830
|
+
// Opens in Data Explorer's Queries nav item once the Add Pin panel has found that app
|
|
2831
|
+
const deApp = this.HasDataExplorerApp
|
|
2832
|
+
? this.appManager.GetAllApps().find(a => a.Name === 'Data Explorer')
|
|
2833
|
+
: null;
|
|
2296
2834
|
if (deApp) {
|
|
2297
2835
|
void this.navigationService.SwitchToApp(deApp.ID, 'Queries', { queryId: queryId });
|
|
2298
2836
|
}
|
|
2299
2837
|
else {
|
|
2300
2838
|
this.navigationService.OpenQuery(queryId, pin.DisplayName);
|
|
2301
2839
|
}
|
|
2302
|
-
|
|
2840
|
+
return true;
|
|
2303
2841
|
}
|
|
2304
2842
|
case 'Records': {
|
|
2305
2843
|
const entityName = (config['Entity'] || config['entity']);
|
|
2306
2844
|
const recordId = config['recordId'];
|
|
2307
|
-
if (entityName
|
|
2308
|
-
const compositeKey = this.buildCompositeKeyForRecord(entityName, recordId);
|
|
2309
|
-
if (compositeKey) {
|
|
2310
|
-
this.navigationService.OpenEntityRecord(entityName, compositeKey);
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
else {
|
|
2845
|
+
if (!entityName || !recordId) {
|
|
2314
2846
|
console.warn('[Pin Click] Records pin missing Entity or recordId', config);
|
|
2847
|
+
return false;
|
|
2315
2848
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
const appName = config['appName'];
|
|
2322
|
-
const queryParams = config['queryParams'];
|
|
2323
|
-
if (appName) {
|
|
2324
|
-
const app = this.appManager.GetAllApps().find(a => a.Name === appName);
|
|
2325
|
-
if (app) {
|
|
2326
|
-
// Pass query params INTO SwitchToApp so they're applied synchronously when the
|
|
2327
|
-
// target tab activates — before a cached resource component reattaches. The old
|
|
2328
|
-
// post-hoc UpdateActiveTabQueryParams() in a .then() raced the cache reattach and
|
|
2329
|
-
// lost: e.g. two conversation pins both landed on whatever chat was already open.
|
|
2330
|
-
void this.navigationService.SwitchToApp(app.ID, navItemName, queryParams);
|
|
2331
|
-
}
|
|
2332
|
-
else {
|
|
2333
|
-
console.warn(`[Pin Click] Custom pin: app "${appName}" not found`, config);
|
|
2334
|
-
}
|
|
2335
|
-
}
|
|
2336
|
-
else {
|
|
2337
|
-
console.warn('[Pin Click] Custom pin missing appName', config);
|
|
2338
|
-
}
|
|
2339
|
-
break;
|
|
2849
|
+
const compositeKey = this.buildCompositeKeyForRecord(entityName, recordId);
|
|
2850
|
+
if (!compositeKey)
|
|
2851
|
+
return false;
|
|
2852
|
+
this.navigationService.OpenEntityRecord(entityName, compositeKey);
|
|
2853
|
+
return true;
|
|
2340
2854
|
}
|
|
2855
|
+
case 'Custom':
|
|
2856
|
+
return this.openAppPagePin(config);
|
|
2341
2857
|
case 'Actions': {
|
|
2342
2858
|
const actionId = config['actionId'];
|
|
2343
2859
|
if (!actionId) {
|
|
2344
2860
|
console.warn('[Pin Click] Action pin missing actionId', config);
|
|
2345
|
-
|
|
2861
|
+
return false;
|
|
2346
2862
|
}
|
|
2347
2863
|
this.ActionRunnerPin = pin;
|
|
2348
2864
|
this.ActionRunnerDialogVisible = true;
|
|
2349
2865
|
this.cdr.markForCheck();
|
|
2350
|
-
|
|
2866
|
+
return true;
|
|
2351
2867
|
}
|
|
2352
2868
|
default:
|
|
2353
|
-
console.warn('[Pin Click] Unrecognized resource type',
|
|
2354
|
-
|
|
2869
|
+
console.warn('[Pin Click] Unrecognized resource type', resourceType, 'for pin', pin.DisplayName, config);
|
|
2870
|
+
return false;
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
/** Opens an app page pin (a Custom pin): a nav item of an app, found by the app's name. Returns false when the pin is broken. */
|
|
2874
|
+
openAppPagePin(config) {
|
|
2875
|
+
// Custom resources are nav items within apps — always use app name, never ID
|
|
2876
|
+
const navItemName = config['navItemName'];
|
|
2877
|
+
const appName = config['appName'];
|
|
2878
|
+
const queryParams = config['queryParams'];
|
|
2879
|
+
if (!appName) {
|
|
2880
|
+
console.warn('[Pin Click] Custom pin missing appName', config);
|
|
2881
|
+
return false;
|
|
2882
|
+
}
|
|
2883
|
+
const app = this.appManager.GetAllApps().find(a => a.Name === appName);
|
|
2884
|
+
if (!app) {
|
|
2885
|
+
console.warn(`[Pin Click] Custom pin: app "${appName}" not found`, config);
|
|
2886
|
+
return false;
|
|
2355
2887
|
}
|
|
2888
|
+
// SwitchToApp gets the query params, so the target tab has them when it activates, before a cached resource
|
|
2889
|
+
// component reattaches: the page opens on the state the pin names.
|
|
2890
|
+
void this.navigationService.SwitchToApp(app.ID, navItemName, queryParams);
|
|
2891
|
+
return true;
|
|
2356
2892
|
}
|
|
2357
2893
|
/**
|
|
2358
|
-
*
|
|
2359
|
-
* Handles legacy pins that may have stored a UUID resourceTypeId or
|
|
2360
|
-
* a raw config.resourceType string instead of the canonical type names.
|
|
2361
|
-
*/
|
|
2362
|
-
resolveStoredResourceType(pin) {
|
|
2363
|
-
const rt = pin.ResourceType;
|
|
2364
|
-
const config = pin.Configuration;
|
|
2365
|
-
// Already a known canonical type
|
|
2366
|
-
const knownTypes = ['Dashboards', 'User Views', 'Queries', 'Reports', 'Records', 'Custom', 'Actions'];
|
|
2367
|
-
if (knownTypes.includes(rt))
|
|
2368
|
-
return rt;
|
|
2369
|
-
// Check the config's own resourceType field
|
|
2370
|
-
const configRt = config['resourceType'];
|
|
2371
|
-
if (configRt && knownTypes.includes(configRt))
|
|
2372
|
-
return configRt;
|
|
2373
|
-
// Fall back to detecting by config keys
|
|
2374
|
-
if (config['dashboardId'])
|
|
2375
|
-
return 'Dashboards';
|
|
2376
|
-
if (config['viewId'])
|
|
2377
|
-
return 'User Views';
|
|
2378
|
-
if (config['queryId'])
|
|
2379
|
-
return 'Queries';
|
|
2380
|
-
if (config['reportId'])
|
|
2381
|
-
return 'Reports';
|
|
2382
|
-
if ((config['Entity'] || config['entity']) && config['recordId'])
|
|
2383
|
-
return 'Records';
|
|
2384
|
-
if (config['actionId'])
|
|
2385
|
-
return 'Actions';
|
|
2386
|
-
if (config['navItemName'])
|
|
2387
|
-
return 'Custom';
|
|
2388
|
-
return rt; // Give up and return whatever was stored
|
|
2389
|
-
}
|
|
2390
|
-
/**
|
|
2391
|
-
* Toggle edit mode for pins
|
|
2894
|
+
* Toggle edit mode for pins. Entering edit mode opens a collapsed Pinned section.
|
|
2392
2895
|
*/
|
|
2393
2896
|
ToggleEditMode() {
|
|
2394
2897
|
this.EditMode = !this.EditMode;
|
|
2395
|
-
if (
|
|
2898
|
+
if (this.EditMode) {
|
|
2899
|
+
this.openPinnedSection();
|
|
2900
|
+
}
|
|
2901
|
+
else {
|
|
2396
2902
|
this.EditingPinId = null;
|
|
2397
2903
|
this.EditingGroupName = null;
|
|
2398
2904
|
}
|
|
@@ -2407,6 +2913,27 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2407
2913
|
UserInfoEngine.Instance.SetSettingDebounced('HomeApp.HidePinEmptyState', 'true');
|
|
2408
2914
|
this.cdr.markForCheck();
|
|
2409
2915
|
}
|
|
2916
|
+
/** Opens or collapses the Pinned section, saves the choice for the user and reports it to the agent. */
|
|
2917
|
+
OnPinnedExpandedChange(expanded) {
|
|
2918
|
+
this.PinnedExpanded = expanded;
|
|
2919
|
+
this.sectionStateChanged(PINNED_COLLAPSED_SETTING, expanded);
|
|
2920
|
+
}
|
|
2921
|
+
/** Reads whether the Pinned section is open. 'true' means collapsed; a missing setting means open. */
|
|
2922
|
+
loadSectionStates() {
|
|
2923
|
+
this.PinnedExpanded = UserInfoEngine.Instance.GetSetting(PINNED_COLLAPSED_SETTING) !== 'true';
|
|
2924
|
+
}
|
|
2925
|
+
/** Saves a section's state for the user ('true' when collapsed), reports it to the agent and renders. */
|
|
2926
|
+
sectionStateChanged(settingKey, expanded) {
|
|
2927
|
+
UserInfoEngine.Instance.SetSettingDebounced(settingKey, expanded ? 'false' : 'true');
|
|
2928
|
+
this.publishAgentContext();
|
|
2929
|
+
this.cdr.markForCheck();
|
|
2930
|
+
}
|
|
2931
|
+
/** Opens the Pinned section when it is collapsed, so edit mode or a new pin shows. */
|
|
2932
|
+
openPinnedSection() {
|
|
2933
|
+
if (!this.PinnedExpanded) {
|
|
2934
|
+
this.OnPinnedExpandedChange(true);
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2410
2937
|
/**
|
|
2411
2938
|
* Remove a pin
|
|
2412
2939
|
*/
|
|
@@ -2414,22 +2941,96 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2414
2941
|
this.pinService.RemovePin(pinId);
|
|
2415
2942
|
}
|
|
2416
2943
|
/**
|
|
2417
|
-
*
|
|
2944
|
+
* Starts renaming a pin: shows its rename box, with focus in it and the name selected. A dashboard pin is renamed
|
|
2945
|
+
* only by a user who can edit its dashboard; other users are told why not.
|
|
2418
2946
|
*/
|
|
2419
2947
|
StartEditingPin(pinId, event) {
|
|
2420
2948
|
event.stopPropagation();
|
|
2949
|
+
const pin = this.PinnedItems.find(p => p.Id === pinId);
|
|
2950
|
+
if (pin && !this.canRenamePin(pin)) {
|
|
2951
|
+
this.notifyCannotRename(pin);
|
|
2952
|
+
return;
|
|
2953
|
+
}
|
|
2421
2954
|
this.EditingPinId = pinId;
|
|
2422
|
-
this.
|
|
2955
|
+
this.focusPinNameInput();
|
|
2423
2956
|
}
|
|
2424
2957
|
/**
|
|
2425
|
-
*
|
|
2958
|
+
* Saves the name typed in a pin's rename box and closes the box. A dashboard pin renames its dashboard, since it
|
|
2959
|
+
* shows the dashboard's name; other pins rename only the pin. An empty or unchanged name changes nothing. A call
|
|
2960
|
+
* after the rename has ended does nothing: the browser can blur the box as it goes away.
|
|
2426
2961
|
*/
|
|
2427
2962
|
SavePinName(pinId, newName) {
|
|
2428
|
-
if (
|
|
2429
|
-
|
|
2430
|
-
}
|
|
2963
|
+
if (this.EditingPinId !== pinId)
|
|
2964
|
+
return;
|
|
2431
2965
|
this.EditingPinId = null;
|
|
2432
2966
|
this.cdr.markForCheck();
|
|
2967
|
+
const pin = this.PinnedItems.find(p => p.Id === pinId);
|
|
2968
|
+
const name = newName.trim();
|
|
2969
|
+
if (!pin || !name || name === this.PinName(pin))
|
|
2970
|
+
return;
|
|
2971
|
+
const dashboard = this.pinDashboard(pin);
|
|
2972
|
+
if (dashboard) {
|
|
2973
|
+
void this.renameDashboard(dashboard, pin, name);
|
|
2974
|
+
return;
|
|
2975
|
+
}
|
|
2976
|
+
this.pinService.UpdatePin(pinId, { DisplayName: name });
|
|
2977
|
+
}
|
|
2978
|
+
/** Enter in a pin's rename box: saves the name, then moves focus to Done, since the box goes away. */
|
|
2979
|
+
OnPinNameEnter(pinId, event) {
|
|
2980
|
+
this.SavePinName(pinId, this.GetInputValue(event));
|
|
2981
|
+
this.focusShownView();
|
|
2982
|
+
}
|
|
2983
|
+
/** Renders Home, then puts focus in the open rename box and selects the name, so typing replaces it. */
|
|
2984
|
+
focusPinNameInput() {
|
|
2985
|
+
this.focusInHome('.pin-card .pin-name-input')?.select();
|
|
2986
|
+
}
|
|
2987
|
+
/** The dashboard a dashboard pin shows, from the dashboard cache. Null for other pins, and when the cache lacks it. */
|
|
2988
|
+
pinDashboard(pin) {
|
|
2989
|
+
return FindDashboard(this.accessibleDashboards(), DashboardIdOfPin(pin));
|
|
2990
|
+
}
|
|
2991
|
+
/** True when the user may rename the pin: a pin that shows no cached dashboard, or a dashboard pin whose dashboard the user can edit. */
|
|
2992
|
+
canRenamePin(pin) {
|
|
2993
|
+
const dashboard = this.pinDashboard(pin);
|
|
2994
|
+
return !dashboard || DashboardEngine.Instance.CanUserEditDashboard(dashboard.ID, this.ProviderToUse.CurrentUser.ID);
|
|
2995
|
+
}
|
|
2996
|
+
/** Tells the user that only people who can edit the pin's dashboard can rename the pin. */
|
|
2997
|
+
notifyCannotRename(pin) {
|
|
2998
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Only people who can edit "${this.PinName(pin)}" can rename it`, 'info', 3000);
|
|
2999
|
+
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Renames the dashboard a pin shows, and keeps the pin's stored name in step: the name the pin shows when the cache
|
|
3002
|
+
* lacks the dashboard. It renames the cache's own dashboard object, so the switcher, the pin names and an editor that
|
|
3003
|
+
* shows the dashboard have the new name at once. While a save of that object runs (an editor's Save, for example),
|
|
3004
|
+
* it renames nothing and tells the user: its own save would join the running one and write nothing. A failed save
|
|
3005
|
+
* puts the old name back and tells the user.
|
|
3006
|
+
*/
|
|
3007
|
+
async renameDashboard(dashboard, pin, name) {
|
|
3008
|
+
if (dashboard.IsSaving) {
|
|
3009
|
+
MJNotificationService.Instance.CreateSimpleNotification(`"${dashboard.Name}" is being saved. Rename it again in a moment.`, 'info', 3000);
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
3012
|
+
const previous = dashboard.Name;
|
|
3013
|
+
dashboard.Name = name;
|
|
3014
|
+
this.refreshPinnedDashboards();
|
|
3015
|
+
const failure = await this.saveRenamedDashboard(dashboard);
|
|
3016
|
+
if (failure !== null) {
|
|
3017
|
+
dashboard.Name = previous;
|
|
3018
|
+
this.refreshPinnedDashboards();
|
|
3019
|
+
LogError(`Home: could not rename the dashboard "${previous}": ${failure}`);
|
|
3020
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Could not rename "${previous}"`, 'error', 3000);
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
this.pinService.UpdatePin(pin.Id, { DisplayName: name });
|
|
3024
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Renamed the dashboard to "${name}"`, 'success', 2000);
|
|
3025
|
+
}
|
|
3026
|
+
/** Saves a renamed dashboard. Returns null when it saved, else why not. Never throws. */
|
|
3027
|
+
async saveRenamedDashboard(dashboard) {
|
|
3028
|
+
try {
|
|
3029
|
+
return (await dashboard.Save()) ? null : dashboard.LatestResult?.CompleteMessage ?? 'unknown error';
|
|
3030
|
+
}
|
|
3031
|
+
catch (error) {
|
|
3032
|
+
return errorMessage(error);
|
|
3033
|
+
}
|
|
2433
3034
|
}
|
|
2434
3035
|
/**
|
|
2435
3036
|
* Extract input value from a DOM event (strict template helper)
|
|
@@ -2472,6 +3073,10 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2472
3073
|
GetPinsInGroup(groupName) {
|
|
2473
3074
|
return this.pinService.GetPinsInGroup(groupName);
|
|
2474
3075
|
}
|
|
3076
|
+
/** The name a pin shows: a dashboard pin shows its dashboard's name from the cache; other pins show their own. */
|
|
3077
|
+
PinName(pin) {
|
|
3078
|
+
return this.pinDashboardNames.get(pin.Id) ?? pin.DisplayName;
|
|
3079
|
+
}
|
|
2475
3080
|
/**
|
|
2476
3081
|
* Get icon for a pin based on resource type and metadata
|
|
2477
3082
|
*/
|
|
@@ -2549,32 +3154,89 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2549
3154
|
// PIN CONTEXT MENU (ELLIPSIS)
|
|
2550
3155
|
// =============================================
|
|
2551
3156
|
/**
|
|
2552
|
-
*
|
|
3157
|
+
* Opens the pin options menu under the pin's ellipsis button, right-aligned and inside the viewport, and moves
|
|
3158
|
+
* focus to its first row. A click elsewhere, Escape or Tab closes it.
|
|
2553
3159
|
*/
|
|
2554
3160
|
ShowPinMenu(event, pin) {
|
|
2555
3161
|
event.stopPropagation();
|
|
2556
3162
|
event.preventDefault();
|
|
3163
|
+
const trigger = event.currentTarget;
|
|
3164
|
+
if (!(trigger instanceof HTMLElement)) {
|
|
3165
|
+
return;
|
|
3166
|
+
}
|
|
3167
|
+
const anchor = MenuAnchorOf(trigger);
|
|
3168
|
+
this.pinMenuTrigger = trigger;
|
|
2557
3169
|
this.PinMenuPin = pin;
|
|
2558
|
-
this.PinMenuX = event.clientX;
|
|
2559
|
-
this.PinMenuY = event.clientY;
|
|
2560
3170
|
this.PinMenuVisible = true;
|
|
2561
|
-
this.
|
|
2562
|
-
//
|
|
3171
|
+
this.placePinMenu(anchor, 0);
|
|
3172
|
+
// Render the menu with no max height to measure its full height, then place it again with that height
|
|
3173
|
+
this.PinMenuMaxHeight = null;
|
|
3174
|
+
this.cdr.detectChanges();
|
|
3175
|
+
this.placePinMenu(anchor, this.pinMenuEl?.nativeElement.offsetHeight ?? 0);
|
|
3176
|
+
this.cdr.detectChanges();
|
|
3177
|
+
this.pinMenuRows()[0]?.focus({ preventScroll: true });
|
|
3178
|
+
this.watchPinMenuDismiss();
|
|
3179
|
+
}
|
|
3180
|
+
/**
|
|
3181
|
+
* Keys in the pin options menu: ArrowDown, ArrowUp, Home and End move between the rows. Escape closes the menu
|
|
3182
|
+
* and puts focus back on its button. Tab closes it too, and the browser moves focus on from the button.
|
|
3183
|
+
*/
|
|
3184
|
+
OnPinMenuKeydown(event) {
|
|
3185
|
+
if (event.key === 'Escape') {
|
|
3186
|
+
event.preventDefault();
|
|
3187
|
+
this.closePinMenuToTrigger();
|
|
3188
|
+
}
|
|
3189
|
+
else if (event.key === 'Tab') {
|
|
3190
|
+
this.closePinMenuToTrigger();
|
|
3191
|
+
}
|
|
3192
|
+
else {
|
|
3193
|
+
this.focusPinMenuRow(event);
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
/** Moves focus to the menu row that ArrowDown, ArrowUp, Home or End picks. Other keys do nothing. */
|
|
3197
|
+
focusPinMenuRow(event) {
|
|
3198
|
+
const rows = this.pinMenuRows();
|
|
3199
|
+
const next = NextMenuFocusIndex(event.key, rows.findIndex(row => row === document.activeElement), rows.length);
|
|
3200
|
+
if (next !== null) {
|
|
3201
|
+
event.preventDefault();
|
|
3202
|
+
rows[next].focus();
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
/** The menu's rows, in order: its menuitem buttons. */
|
|
3206
|
+
pinMenuRows() {
|
|
3207
|
+
return Array.from(this.pinMenuEl?.nativeElement.querySelectorAll('[role="menuitem"]') ?? []);
|
|
3208
|
+
}
|
|
3209
|
+
/** Closes the pin options menu and puts focus back on the button that opened it. */
|
|
3210
|
+
closePinMenuToTrigger() {
|
|
3211
|
+
const trigger = this.pinMenuTrigger;
|
|
3212
|
+
this.HidePinMenu();
|
|
3213
|
+
trigger?.focus();
|
|
3214
|
+
}
|
|
3215
|
+
/**
|
|
3216
|
+
* Places the pin options menu next to its button and limits its height to the room on that side. A height of 0
|
|
3217
|
+
* places it below the button.
|
|
3218
|
+
*/
|
|
3219
|
+
placePinMenu(anchor, height) {
|
|
3220
|
+
const place = PlaceMenu(anchor, PIN_MENU_WIDTH, height, 'right', { Width: window.innerWidth, Height: window.innerHeight });
|
|
3221
|
+
this.PinMenuX = place.Left;
|
|
3222
|
+
this.PinMenuY = place.Top;
|
|
3223
|
+
this.PinMenuMaxHeight = place.MaxHeight;
|
|
3224
|
+
}
|
|
3225
|
+
/** Closes the pin options menu on the next click anywhere or on Escape. */
|
|
3226
|
+
watchPinMenuDismiss() {
|
|
2563
3227
|
setTimeout(() => {
|
|
2564
|
-
const
|
|
3228
|
+
const close = () => {
|
|
2565
3229
|
this.HidePinMenu();
|
|
2566
|
-
document.removeEventListener('click',
|
|
2567
|
-
document.removeEventListener('keydown',
|
|
3230
|
+
document.removeEventListener('click', close);
|
|
3231
|
+
document.removeEventListener('keydown', onKeydown);
|
|
2568
3232
|
};
|
|
2569
|
-
const
|
|
2570
|
-
if (
|
|
2571
|
-
|
|
2572
|
-
document.removeEventListener('click', clickHandler);
|
|
2573
|
-
document.removeEventListener('keydown', keyHandler);
|
|
3233
|
+
const onKeydown = (event) => {
|
|
3234
|
+
if (event.key === 'Escape') {
|
|
3235
|
+
close();
|
|
2574
3236
|
}
|
|
2575
3237
|
};
|
|
2576
|
-
document.addEventListener('click',
|
|
2577
|
-
document.addEventListener('keydown',
|
|
3238
|
+
document.addEventListener('click', close);
|
|
3239
|
+
document.addEventListener('keydown', onKeydown);
|
|
2578
3240
|
}, 0);
|
|
2579
3241
|
}
|
|
2580
3242
|
/**
|
|
@@ -2583,18 +3245,30 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2583
3245
|
HidePinMenu() {
|
|
2584
3246
|
this.PinMenuVisible = false;
|
|
2585
3247
|
this.PinMenuPin = null;
|
|
3248
|
+
this.pinMenuTrigger = null;
|
|
2586
3249
|
this.cdr.markForCheck();
|
|
2587
3250
|
}
|
|
2588
3251
|
/**
|
|
2589
|
-
* Edit a pin
|
|
3252
|
+
* Edit in a pin's menu: closes the menu, puts the pins in edit mode (opening a collapsed Pinned section) and starts
|
|
3253
|
+
* renaming the pin, with focus in its rename box. For a dashboard pin the user cannot rename, it says why and moves
|
|
3254
|
+
* focus to Done instead.
|
|
2590
3255
|
*/
|
|
2591
3256
|
OnPinMenuEdit() {
|
|
2592
|
-
|
|
2593
|
-
this.EditMode = true;
|
|
2594
|
-
this.EditingPinId = this.PinMenuPin.Id;
|
|
2595
|
-
this.cdr.markForCheck();
|
|
2596
|
-
}
|
|
3257
|
+
const pin = this.PinMenuPin;
|
|
2597
3258
|
this.HidePinMenu();
|
|
3259
|
+
if (!pin)
|
|
3260
|
+
return;
|
|
3261
|
+
this.EditMode = true;
|
|
3262
|
+
this.openPinnedSection();
|
|
3263
|
+
if (this.canRenamePin(pin)) {
|
|
3264
|
+
this.EditingPinId = pin.Id;
|
|
3265
|
+
this.focusPinNameInput();
|
|
3266
|
+
}
|
|
3267
|
+
else {
|
|
3268
|
+
this.EditingPinId = null;
|
|
3269
|
+
this.notifyCannotRename(pin);
|
|
3270
|
+
this.focusShownView();
|
|
3271
|
+
}
|
|
2598
3272
|
}
|
|
2599
3273
|
/**
|
|
2600
3274
|
* Move a pin to a different group
|
|
@@ -2739,8 +3413,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2739
3413
|
}));
|
|
2740
3414
|
// Load apps with their nav items
|
|
2741
3415
|
await this.loadAvailableApps();
|
|
2742
|
-
//
|
|
2743
|
-
// are accessible through its nav items, no need for standalone sections
|
|
3416
|
+
// Query pins open in Data Explorer when the user has that app (see OnPinClick)
|
|
2744
3417
|
this.HasDataExplorerApp = this.AvailableApps.some(a => a.appName === 'Data Explorer');
|
|
2745
3418
|
}
|
|
2746
3419
|
/**
|
|
@@ -2811,6 +3484,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2811
3484
|
};
|
|
2812
3485
|
});
|
|
2813
3486
|
MJNotificationService.Instance.CreateSimpleNotification(`"${navItemLabel}" pinned to Home`, 'success', 3000);
|
|
3487
|
+
this.openPinnedSection();
|
|
2814
3488
|
this.cdr.markForCheck();
|
|
2815
3489
|
}
|
|
2816
3490
|
}
|
|
@@ -2843,6 +3517,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2843
3517
|
if (added) {
|
|
2844
3518
|
this.updatePanelPinnedState(resourceType, id, true);
|
|
2845
3519
|
MJNotificationService.Instance.CreateSimpleNotification(`"${name}" pinned to Home`, 'success', 3000);
|
|
3520
|
+
this.openPinnedSection();
|
|
2846
3521
|
}
|
|
2847
3522
|
}
|
|
2848
3523
|
// =============================================
|
|
@@ -2886,6 +3561,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2886
3561
|
const added = this.pinService.AddPin(input);
|
|
2887
3562
|
if (added) {
|
|
2888
3563
|
MJNotificationService.Instance.CreateSimpleNotification(`"${p.DisplayName}" pinned to Home`, 'success', 3000);
|
|
3564
|
+
this.openPinnedSection();
|
|
2889
3565
|
}
|
|
2890
3566
|
else {
|
|
2891
3567
|
MJNotificationService.Instance.CreateSimpleNotification('A pin with the same title and config already exists.', 'warning', 3000);
|
|
@@ -2936,63 +3612,62 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
2936
3612
|
}
|
|
2937
3613
|
static ɵfac = function HomeDashboardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || HomeDashboardComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i2.RecentAccessService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
2938
3614
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: HomeDashboardComponent, selectors: [["mj-home-dashboard"]], viewQuery: function HomeDashboardComponent_Query(rf, ctx) { if (rf & 1) {
|
|
2939
|
-
i0.ɵɵviewQuery(_c0, 5);
|
|
3615
|
+
i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(_c2, 5);
|
|
2940
3616
|
} if (rf & 2) {
|
|
2941
3617
|
let _t;
|
|
2942
3618
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.AppConfigDialog = _t.first);
|
|
2943
|
-
|
|
3619
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.pinMenuEl = _t.first);
|
|
3620
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dashboardEditor = _t.first);
|
|
3621
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 16, vars: 19, consts: [["homeDashboardTitle", ""], ["appConfigDialog", ""], ["dashboardEditor", ""], ["pinMenu", ""], [1, "home-dashboard"], [1, "main-content"], [1, "home-overview"], ["BodyStyle", "card", 1, "home-dashboard-view", 3, "Provider", "DashboardId", "StartInEditMode", "TitleTemplate", "ShowOpenInDashboards"], ["role", "menu", 1, "pin-context-menu", 3, "left", "top", "max-height"], [3, "Result", "Visible", "ActionID", "ActionName", "ActionDescription"], [3, "Result", "Visible", "Pin"], [3, "Confirmed", "Cancelled", "Visible", "MaxLength", "Processing"], [1, "loading-container"], [1, "quick-access-sidebar"], ["title", "Quick Access", 1, "sidebar-fab-toggle"], [3, "ShowDialogChange", "ConfigSaved", "ShowDialog"], [1, "home-header"], [1, "greeting-section"], [1, "date"], [1, "pinned-section", 3, "ExpandedChange", "Bare", "TitleIconMuted", "HeadingLevel", "FlushBody", "Expanded"], ["mjAccordionTitle", ""], ["mjAccordionActions", ""], ["mjAccordionBody", ""], [1, "apps-section"], [1, "section-title"], [1, "apps-grid"], [1, "app-card", 3, "mjClickable", "TestId", "--app-color"], ["Icon", "fa-solid fa-folder-open", "Title", "No Applications Available", "Message", "You don't have any applications configured yet.", "ActionText", "Configure Applications", "ActionIcon", "fa-solid fa-gear"], [1, "pinned-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-thumbtack"], [1, "pinned-actions"], ["type", "button", "mjButton", "", "Variant", "success", "Size", "sm"], ["type", "button", "mjButton", "", "Variant", "success", "Size", "sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], [1, "pin-action-label"], ["type", "button", "mjButton", "", "Variant", "primary", "Size", "sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["Look", "button", "Align", "right", "Label", "Dashboards", 3, "Pick", "New", "ManagePins", "Dashboards", "CurrentId"], ["type", "button", "mjButton", "", "Variant", "secondary", "Size", "sm"], ["type", "button", "mjButton", "", "Variant", "secondary", "Size", "sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-pen"], [1, "pinned-body"], [1, "edit-mode-banner"], [1, "pin-empty-state"], [1, "pin-grid"], [1, "fa-solid", "fa-arrows-up-down-left-right"], ["type", "button", "title", "Hide this", 1, "pin-empty-close"], ["Icon", "fa-solid fa-thumbtack", "Title", "No pinned items yet", "Message", "Pin your favorite dashboards, views, queries, and reports for quick access."], ["actions", "", "mjButton", "", "variant", "primary", 3, "click"], [1, "fa-solid", "fa-plus"], ["actions", "", "mjButton", "", "variant", "flat"], ["type", "button", "title", "Hide this", 1, "pin-empty-close", 3, "click"], [1, "fa-solid", "fa-xmark"], ["actions", "", "mjButton", "", "variant", "flat", 3, "click"], [1, "add-pin-card"], [1, "group-header"], [1, "pin-card", 3, "edit-mode", "dragging", "drag-over", "menu-open", "draggable"], [1, "group-name-input", 3, "value"], [1, "group-name"], [1, "group-line"], [1, "group-count"], [1, "group-edit-controls"], [1, "group-name-input", 3, "blur", "keydown.enter", "value"], [1, "group-name", 3, "click"], ["type", "button", 1, "group-edit-btn", "danger", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-folder-minus"], [1, "pin-card", 3, "dragstart", "dragover", "dragleave", "drop", "dragend", "click", "draggable"], [1, "edit-controls"], [1, "pin-thumbnail"], [1, "pin-thumbnail", "action-mode", 3, "background"], [1, "pin-thumbnail", "icon-mode"], [1, "pin-info"], [1, "pin-name-input", 3, "value"], [1, "pin-name"], [1, "pin-meta"], ["aria-hidden", "true", 1, "fa-solid", "fa-gauge-high"], [1, "pin-kind"], [1, "drag-handle"], ["aria-hidden", "true", 1, "fa-solid", "fa-grip-vertical"], [1, "edit-card-actions"], ["type", "button", "aria-label", "Remove pin", "title", "Remove pin", 1, "edit-card-btn", "delete", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], [3, "src", "alt"], [1, "pin-overlay"], [1, "pin-thumbnail", "action-mode"], ["aria-hidden", "true"], [1, "pin-name-input", 3, "blur", "keydown.enter", "click", "value"], [1, "pin-name", 3, "click"], [1, "pin-name-text"], ["type", "button", "title", "Pin options", "aria-haspopup", "menu", 1, "more-btn"], ["type", "button", "title", "Pin options", "aria-haspopup", "menu", 1, "more-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-ellipsis"], [1, "add-pin-card", 3, "click"], [1, "app-card", 3, "click", "mjClickable", "TestId"], ["aria-hidden", "true", 1, "app-icon"], [1, "app-info"], [1, "app-name"], [1, "app-description"], ["Icon", "fa-solid fa-folder-open", "Title", "No Applications Available", "Message", "You don't have any applications configured yet.", "ActionText", "Configure Applications", "ActionIcon", "fa-solid fa-gear", 3, "Action"], ["BodyStyle", "card", 1, "home-dashboard-view", 3, "StartInEditModeChange", "Loaded", "EditingChange", "NameChanged", "Saved", "LoadFailed", "OpenInDashboardsRequested", "NavigationRequested", "Provider", "DashboardId", "StartInEditMode", "TitleTemplate", "ShowOpenInDashboards"], [1, "dashboard-title"], ["aria-label", "Breadcrumb", 1, "dashboard-crumb"], ["type", "button", 1, "crumb-home", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-house"], ["Look", "title", "Align", "left", 3, "Pick", "New", "ManagePins", "HeadingLevel", "Label", "Dashboards", "CurrentId"], ["role", "menu", 1, "pin-context-menu", 3, "keydown"], ["type", "button", "role", "menuitem", 1, "pin-context-item", 3, "click"], ["role", "separator", 1, "pin-context-divider"], ["role", "group"], [1, "pin-context-item", "submenu-header", 3, "id"], ["aria-hidden", "true", 1, "fa-solid", "fa-folder"], ["type", "button", "role", "menuitem", 1, "pin-context-item", "submenu-item"], ["type", "button", "role", "menuitem", 1, "pin-context-item", "danger", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-thumbtack-slash"], ["type", "button", "role", "menuitem", 1, "pin-context-item", "submenu-item", 3, "click"], [1, "slide-panel-backdrop", 3, "click"], [1, "slide-panel"], [1, "slide-panel-header"], [1, "fa-solid", "fa-thumbtack"], [1, "slide-panel-close", 3, "click"], [1, "search-box"], [1, "search-input-wrapper"], [1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search apps, dashboards, views, queries...", 3, "ngModelChange", "ngModel"], [1, "group-selector"], [1, "fa-solid", "fa-folder"], [3, "ngModelChange", "ngModel"], ["value", ""], [3, "value"], ["value", "__new__"], [1, "new-group-row"], [1, "panel-results"], [1, "panel-loading"], ["type", "text", "placeholder", "Enter new group name...", 1, "new-group-input", 3, "ngModelChange", "ngModel"], ["text", "Loading resources...", "size", "small"], ["Size", "sm", 1, "panel-section", 3, "FlushBody", "Expanded"], ["Size", "sm", 1, "panel-section", 3, "ExpandedChange", "FlushBody", "Expanded"], [1, "fa-solid", "fa-grid-2"], [1, "mj-accordion-badge", "mj-accordion-badge--right"], [1, "panel-app-header"], [1, "panel-app-icon"], [1, "panel-app-name"], [1, "panel-item", "panel-nav-item"], [1, "panel-item-icon"], [1, "panel-item-info"], [1, "panel-item-name"], [1, "panel-item-action"], [1, "pinned-badge"], [1, "pin-btn"], [1, "fa-solid", "fa-check"], [1, "pin-btn", 3, "click"], [1, "fa-solid", "fa-gauge-high"], [1, "panel-item"], [1, "panel-item-icon", 2, "background", "color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))"], [1, "fa-solid", "fa-gauge-high", 2, "color", "var(--mj-brand-primary)"], [1, "fa-solid", "fa-table-list"], [1, "fa-solid", "fa-table-list", 2, "color", "var(--mj-brand-primary)"], [1, "panel-item-sub"], [1, "fa-solid", "fa-database"], [1, "fa-solid", "fa-database", 2, "color", "var(--mj-brand-primary)"], [1, "fa-solid", "fa-bolt"], [1, "fa-solid", "fa-bolt", 2, "color", "var(--mj-brand-primary)"], [1, "fa-solid", "fa-sliders"], ["text", "Loading your applications...", "size", "large"], [1, "sidebar-header"], ["title", "Close panel", 1, "sidebar-close-btn", 3, "click"], [1, "sidebar-content"], [1, "sidebar-section", "notifications-section"], [1, "sidebar-section", "favorites-section"], [1, "sidebar-section", "recents-section"], ["Size", "compact", "Icon", "fa-solid fa-inbox", "Title", "No quick access items", 1, "sidebar-empty"], [1, "sidebar-section-title"], [1, "fa-solid", "fa-bell"], [1, "section-badge"], [1, "sidebar-items"], ["testId", "notification-item", 1, "sidebar-item", "notification-item", 3, "mjClickable"], ["testId", "notification-item", 1, "sidebar-item", "notification-item", 3, "click", "mjClickable"], [1, "sidebar-item-info"], [1, "sidebar-item-title"], [1, "sidebar-item-subtitle"], [1, "fa-solid", "fa-star"], [1, "sidebar-loading"], ["testId", "favorite-item", 1, "sidebar-item", "favorite-item", 3, "mjClickable"], ["testId", "favorite-item", 1, "sidebar-item", "favorite-item", 3, "click", "mjClickable"], [1, "sidebar-item-icon"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-clock-rotate-left"], ["testId", "recent-item", 1, "sidebar-item", "recent-item", 3, "mjClickable"], ["testId", "recent-item", 1, "sidebar-item", "recent-item", 3, "click", "mjClickable"], ["title", "Quick Access", 1, "sidebar-fab-toggle", 3, "click"], [1, "fab-badge"]], template: function HomeDashboardComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2944
3622
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
2945
|
-
i0.ɵɵelementStart(0, "div",
|
|
2946
|
-
i0.ɵɵ
|
|
3623
|
+
i0.ɵɵelementStart(0, "div", 4)(1, "div", 5);
|
|
3624
|
+
i0.ɵɵconditionalCreate(2, HomeDashboardComponent_Conditional_2_Template, 18, 9, "div", 6);
|
|
3625
|
+
i0.ɵɵconditionalCreate(3, HomeDashboardComponent_Conditional_3_Template, 2, 5, "mj-dashboard-editor", 7);
|
|
3626
|
+
i0.ɵɵtemplate(4, HomeDashboardComponent_ng_template_4_Template, 10, 4, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
3627
|
+
i0.ɵɵconditionalCreate(6, HomeDashboardComponent_Conditional_6_Template, 20, 10, "div", 8);
|
|
3628
|
+
i0.ɵɵconditionalCreate(7, HomeDashboardComponent_Conditional_7_Template, 27, 4);
|
|
3629
|
+
i0.ɵɵelementStart(8, "mj-action-pin-config-dialog", 9);
|
|
3630
|
+
i0.ɵɵlistener("Result", function HomeDashboardComponent_Template_mj_action_pin_config_dialog_Result_8_listener($event) { return ctx.OnActionConfigResult($event); });
|
|
2947
3631
|
i0.ɵɵelementEnd();
|
|
2948
|
-
i0.ɵɵelementStart(
|
|
2949
|
-
i0.ɵɵ
|
|
2950
|
-
i0.ɵɵelementEnd()()();
|
|
2951
|
-
i0.ɵɵconditionalCreate(8, HomeDashboardComponent_Conditional_8_Template, 11, 4, "div", 6);
|
|
2952
|
-
i0.ɵɵconditionalCreate(9, HomeDashboardComponent_Conditional_9_Template, 19, 5, "div", 7);
|
|
2953
|
-
i0.ɵɵconditionalCreate(10, HomeDashboardComponent_Conditional_10_Template, 27, 4);
|
|
2954
|
-
i0.ɵɵelementStart(11, "mj-action-pin-config-dialog", 8);
|
|
2955
|
-
i0.ɵɵlistener("Result", function HomeDashboardComponent_Template_mj_action_pin_config_dialog_Result_11_listener($event) { return ctx.OnActionConfigResult($event); });
|
|
3632
|
+
i0.ɵɵelementStart(9, "mj-action-pin-runner-dialog", 10);
|
|
3633
|
+
i0.ɵɵlistener("Result", function HomeDashboardComponent_Template_mj_action_pin_runner_dialog_Result_9_listener($event) { return ctx.OnActionRunnerResult($event); });
|
|
2956
3634
|
i0.ɵɵelementEnd();
|
|
2957
|
-
i0.ɵɵelementStart(
|
|
2958
|
-
i0.ɵɵlistener("
|
|
3635
|
+
i0.ɵɵelementStart(10, "mj-dashboard-name-dialog", 11);
|
|
3636
|
+
i0.ɵɵlistener("Confirmed", function HomeDashboardComponent_Template_mj_dashboard_name_dialog_Confirmed_10_listener($event) { return ctx.OnNewDashboardNamed($event); })("Cancelled", function HomeDashboardComponent_Template_mj_dashboard_name_dialog_Cancelled_10_listener() { return ctx.OnNewDashboardCancelled(); });
|
|
2959
3637
|
i0.ɵɵelementEnd();
|
|
2960
|
-
i0.ɵɵconditionalCreate(
|
|
2961
|
-
i0.ɵɵconditionalCreate(14, HomeDashboardComponent_Conditional_14_Template, 8, 1, "div", 11);
|
|
3638
|
+
i0.ɵɵconditionalCreate(11, HomeDashboardComponent_Conditional_11_Template, 2, 0, "div", 12);
|
|
2962
3639
|
i0.ɵɵelementEnd();
|
|
2963
|
-
i0.ɵɵconditionalCreate(
|
|
2964
|
-
i0.ɵɵconditionalCreate(
|
|
2965
|
-
i0.ɵɵelementStart(
|
|
2966
|
-
i0.ɵɵtwoWayListener("ShowDialogChange", function
|
|
2967
|
-
i0.ɵɵlistener("ConfigSaved", function
|
|
3640
|
+
i0.ɵɵconditionalCreate(12, HomeDashboardComponent_Conditional_12_Template, 12, 4, "div", 13);
|
|
3641
|
+
i0.ɵɵconditionalCreate(13, HomeDashboardComponent_Conditional_13_Template, 3, 1, "button", 14);
|
|
3642
|
+
i0.ɵɵelementStart(14, "mj-user-app-config", 15, 1);
|
|
3643
|
+
i0.ɵɵtwoWayListener("ShowDialogChange", function HomeDashboardComponent_Template_mj_user_app_config_ShowDialogChange_14_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.showConfigDialog, $event) || (ctx.showConfigDialog = $event); return i0.ɵɵresetView($event); });
|
|
3644
|
+
i0.ɵɵlistener("ConfigSaved", function HomeDashboardComponent_Template_mj_user_app_config_ConfigSaved_14_listener() { return ctx.onConfigSaved(); });
|
|
2968
3645
|
i0.ɵɵelementEnd()();
|
|
2969
3646
|
} if (rf & 2) {
|
|
2970
|
-
i0.ɵɵclassProp("sidebar-open", ctx.
|
|
2971
|
-
i0.ɵɵadvance(5);
|
|
2972
|
-
i0.ɵɵtextInterpolate2("", ctx.greeting, ", ", ctx.currentUser == null ? null : ctx.currentUser.Name);
|
|
3647
|
+
i0.ɵɵclassProp("sidebar-open", ctx.SidebarOpen && ctx.ShowQuickAccess);
|
|
2973
3648
|
i0.ɵɵadvance(2);
|
|
2974
|
-
i0.ɵɵ
|
|
2975
|
-
i0.ɵɵadvance();
|
|
2976
|
-
i0.ɵɵconditional(!ctx.isLoading ? 8 : -1);
|
|
3649
|
+
i0.ɵɵconditional(ctx.ShowOverview ? 2 : -1);
|
|
2977
3650
|
i0.ɵɵadvance();
|
|
2978
|
-
i0.ɵɵconditional(ctx.
|
|
3651
|
+
i0.ɵɵconditional(ctx.ShowDashboardView && ctx.CurrentDashboardId ? 3 : -1);
|
|
3652
|
+
i0.ɵɵadvance(3);
|
|
3653
|
+
i0.ɵɵconditional(ctx.PinMenuVisible && ctx.PinMenuPin ? 6 : -1);
|
|
2979
3654
|
i0.ɵɵadvance();
|
|
2980
|
-
i0.ɵɵconditional(ctx.AddPanelOpen ?
|
|
3655
|
+
i0.ɵɵconditional(ctx.AddPanelOpen ? 7 : -1);
|
|
2981
3656
|
i0.ɵɵadvance();
|
|
2982
3657
|
i0.ɵɵproperty("Visible", ctx.ActionConfigDialogVisible)("ActionID", ctx.ActionConfigActionId)("ActionName", ctx.ActionConfigActionName)("ActionDescription", ctx.ActionConfigActionDescription);
|
|
2983
3658
|
i0.ɵɵadvance();
|
|
2984
3659
|
i0.ɵɵproperty("Visible", ctx.ActionRunnerDialogVisible)("Pin", ctx.ActionRunnerPin);
|
|
2985
3660
|
i0.ɵɵadvance();
|
|
2986
|
-
i0.ɵɵ
|
|
3661
|
+
i0.ɵɵproperty("Visible", ctx.ShowNewDashboardDialog)("MaxLength", ctx.NewDashboardNameMaxLength)("Processing", ctx.IsCreatingDashboard);
|
|
2987
3662
|
i0.ɵɵadvance();
|
|
2988
|
-
i0.ɵɵconditional(
|
|
3663
|
+
i0.ɵɵconditional(ctx.isLoading ? 11 : -1);
|
|
2989
3664
|
i0.ɵɵadvance();
|
|
2990
|
-
i0.ɵɵconditional(ctx.
|
|
3665
|
+
i0.ɵɵconditional(ctx.ShowQuickAccess ? 12 : -1);
|
|
2991
3666
|
i0.ɵɵadvance();
|
|
2992
|
-
i0.ɵɵconditional(ctx.
|
|
3667
|
+
i0.ɵɵconditional(ctx.ShowQuickAccess && !ctx.SidebarOpen ? 13 : -1);
|
|
2993
3668
|
i0.ɵɵadvance();
|
|
2994
3669
|
i0.ɵɵtwoWayProperty("ShowDialog", ctx.showConfigDialog);
|
|
2995
|
-
} }, dependencies: [i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.MJButtonDirective, i4.MJClickableDirective, i4.MJEmptyStateComponent, i4.MJAccordionPanelComponent, i4.MJAccordionTitleDirective, i4.MJAccordionBodyDirective, i5.LoadingComponent, i6.UserAppConfigComponent, i7.ActionPinConfigDialogComponent, i8.ActionPinRunnerDialogComponent, i9.SlicePipe], styles: [".home-dashboard[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n position: relative;\n}\n\n\n.main-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 32px;\n overflow-y: auto;\n transition: margin-right var(--mj-transition-slow);\n}\n\n\n.home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 320px;\n}\n\n\n.home-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 32px;\n}\n\n.greeting-section[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: var(--mj-text-4xl);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.greeting-section[_ngcontent-%COMP%] .date[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-base);\n color: var(--mj-text-muted);\n}\n\n\n.sidebar-fab-toggle[_ngcontent-%COMP%] {\n position: absolute;\n top: 20px;\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: var(--mj-radius-full);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xl);\n cursor: pointer;\n box-shadow: var(--mj-shadow-brand-md);\n transition: all var(--mj-transition-base);\n z-index: 100;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sidebar-fab-toggle[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n box-shadow: 0 6px 16px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.fab-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n gap: 16px;\n color: var(--mj-text-muted);\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n font-size: var(--mj-text-4xl);\n color: var(--mj-brand-primary);\n}\n\n\n.apps-section[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n}\n\n.section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0 0 24px 0;\n font-size: var(--mj-text-xl);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n.section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n\n.apps-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 20px;\n}\n\n\n.app-card[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition: all 0.25s ease;\n position: relative;\n overflow: hidden;\n}\n\n.app-card[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n background: var(--app-color);\n opacity: 0;\n transition: opacity 0.25s ease;\n}\n\n.app-card[_ngcontent-%COMP%]:hover {\n border-color: var(--app-color);\n box-shadow: var(--mj-shadow-lg);\n transform: translateY(-3px);\n}\n\n.app-card[_ngcontent-%COMP%]:hover::before {\n opacity: 1;\n}\n\n\n.app-icon-wrapper[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.app-icon[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n border-radius: var(--mj-radius-lg);\n background: color-mix(in srgb, var(--app-color) 12%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.25s ease;\n}\n\n.app-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xl);\n color: var(--app-color);\n transition: transform 0.25s ease;\n}\n\n.app-card[_ngcontent-%COMP%]:hover .app-icon[_ngcontent-%COMP%] {\n background: var(--app-color);\n}\n\n.app-card[_ngcontent-%COMP%]:hover .app-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n transform: scale(1.1);\n}\n\n\n.app-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.app-name[_ngcontent-%COMP%] {\n margin: 0 0 4px 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.app-description[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n line-height: var(--mj-leading-snug);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n\n.nav-preview[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n}\n\n.nav-item-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n padding: 3px 8px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n}\n\n.nav-item-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mj-text-muted);\n}\n\n.more-items[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n.app-arrow[_ngcontent-%COMP%] {\n position: absolute;\n right: 14px;\n top: 50%;\n transform: translateY(-50%) translateX(10px);\n opacity: 0;\n transition: all 0.25s ease;\n color: var(--app-color);\n font-size: var(--mj-text-base);\n}\n\n.app-card[_ngcontent-%COMP%]:hover .app-arrow[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n}\n\n\n\n\n.quick-access-sidebar[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform var(--mj-transition-slow);\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.home-dashboard.sidebar-open[_ngcontent-%COMP%] .quick-access-sidebar[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.sidebar-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.sidebar-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sidebar-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n.sidebar-close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.sidebar-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n\n.sidebar-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.sidebar-section[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.sidebar-section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 12px 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n}\n\n.notifications-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-600);\n}\n\n.favorites-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.recents-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.section-badge[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: var(--mj-font-semibold);\n padding: 2px 6px;\n border-radius: var(--mj-radius-md);\n margin-left: auto;\n}\n\n\n.sidebar-items[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sidebar-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.sidebar-item-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n}\n\n.notification-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: var(--mj-color-warning-50);\n}\n\n.notification-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-600);\n}\n\n.favorite-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: var(--mj-color-warning-50);\n}\n\n.favorite-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.recent-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: var(--mj-color-info-50);\n}\n\n.recent-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-item-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.sidebar-item-title[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n padding: 8px 0;\n}\n\n.sidebar-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.sidebar-empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-4xl);\n margin-bottom: 12px;\n}\n\n.sidebar-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n}\n\n\n\n\n\n.pinned-section[_ngcontent-%COMP%] {\n margin-bottom: 32px;\n}\n\n.pinned-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n}\n\n.pinned-header[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.pinned-actions[_ngcontent-%COMP%] {\n margin-left: auto;\n display: flex;\n gap: 8px;\n}\n\n.pin-action-btn[_ngcontent-%COMP%] {\n padding: 6px 14px;\n border-radius: var(--mj-radius-md);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all var(--mj-transition-base);\n}\n\n.pin-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.pin-action-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.pin-action-btn.primary[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.pin-action-btn.done[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-success);\n}\n\n\n.edit-mode-banner[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n border-radius: var(--mj-radius-lg);\n padding: 12px 20px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.edit-mode-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-base);\n}\n\n.edit-mode-banner[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n\n.pin-empty-state[_ngcontent-%COMP%] {\n position: relative;\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n border: 2px dashed var(--mj-border-default);\n}\n\n.pin-empty-close[_ngcontent-%COMP%] {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: var(--mj-text-sm);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.pin-empty-close[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n\n.pin-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 12px;\n}\n\n\n.group-header[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0 4px 0;\n margin-top: 8px;\n}\n\n.group-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.group-line[_ngcontent-%COMP%] {\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.group-count[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-disabled);\n background: var(--mj-bg-surface-card);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.group-name-input[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n padding: 2px 8px;\n background: var(--mj-bg-surface);\n outline: none;\n width: 160px;\n}\n\n.group-edit-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n}\n\n.group-edit-btn[_ngcontent-%COMP%] {\n background: none;\n border: 1px solid transparent;\n color: var(--mj-text-muted);\n font-size: 11px;\n cursor: pointer;\n padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all var(--mj-transition-base);\n}\n\n.group-edit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-default);\n color: var(--mj-text-secondary);\n}\n\n.group-edit-btn.danger[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n\n.pin-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n cursor: pointer;\n transition: all 0.25s ease;\n position: relative;\n}\n\n.pin-card[_ngcontent-%COMP%]:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-border-default));\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.pin-card.edit-mode[_ngcontent-%COMP%] {\n cursor: grab;\n}\n\n.pin-card.edit-mode[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.pin-card.dragging[_ngcontent-%COMP%] {\n opacity: 0.5;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-lg);\n transform: rotate(2deg);\n}\n\n.pin-card.drag-over[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n\n.edit-controls[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n left: 8px;\n right: 8px;\n display: flex;\n justify-content: space-between;\n z-index: 10;\n pointer-events: none;\n}\n\n.edit-controls[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] {\n pointer-events: auto;\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n cursor: grab;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.drag-handle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.edit-card-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.edit-card-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-btn.delete[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n}\n\n\n.pin-thumbnail[_ngcontent-%COMP%] {\n width: 100%;\n aspect-ratio: 16 / 10;\n overflow: hidden;\n position: relative;\n}\n\n.pin-thumbnail[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.pin-thumbnail.icon-mode[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--pin-icon-color, var(--mj-text-muted)) 10%, var(--mj-bg-surface-card));\n}\n\n.pin-thumbnail.icon-mode[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--pin-icon-color, var(--mj-text-muted));\n opacity: 0.7;\n}\n\n\n.pin-thumbnail.action-mode[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse, white);\n background: var(--mj-brand-primary);\n}\n\n.pin-thumbnail.action-mode[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--mj-text-inverse, white);\n}\n\n\n.pin-overlay[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n pointer-events: none;\n background: rgba(0,0,0,0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.pin-card[_ngcontent-%COMP%]:hover .pin-overlay[_ngcontent-%COMP%] {\n opacity: 1;\n pointer-events: auto;\n}\n\n.open-btn[_ngcontent-%COMP%] {\n padding: 8px 20px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n border: none;\n border-radius: var(--mj-radius-md);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n box-shadow: var(--mj-shadow-md);\n}\n\n\n.pin-info[_ngcontent-%COMP%] {\n padding: 10px 12px;\n}\n\n.pin-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-bottom: 4px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%] {\n margin-left: auto;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n font-size: 14px;\n}\n\n\n\n\n.pin-card[_ngcontent-%COMP%]:hover .pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%], \n.pin-card[_ngcontent-%COMP%]:focus-within .pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.pin-name-input[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n padding: 2px 6px;\n width: 100%;\n outline: none;\n background: var(--mj-bg-surface);\n}\n\n.pin-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.pin-meta[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.pin-app-badge[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n\n.add-pin-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-lg);\n border: 2px dashed var(--mj-border-default);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 180px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n gap: 8px;\n color: var(--mj-text-muted);\n}\n\n.add-pin-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-pin-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n}\n\n.add-pin-card[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n}\n\n\n\n\n.pin-context-menu[_ngcontent-%COMP%] {\n position: fixed;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10001;\n overflow: hidden;\n animation: _ngcontent-%COMP%_pinMenuIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinMenuIn {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.pin-context-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 9px 14px;\n cursor: pointer;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.pin-context-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.pin-context-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 16px;\n text-align: center;\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n}\n\n.pin-context-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.pin-context-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.pin-context-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n.pin-context-item.submenu-header[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-medium);\n cursor: default;\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n padding: 6px 14px;\n}\n\n.pin-context-item.submenu-header[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n.pin-context-item.submenu-item[_ngcontent-%COMP%] {\n padding-left: 30px;\n font-size: var(--mj-text-sm);\n}\n\n.pin-context-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n\n.slide-panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 2000;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 400px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-xl);\n z-index: 2001;\n display: flex;\n flex-direction: column;\n animation: _ngcontent-%COMP%_slideIn 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideIn {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n.slide-panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.slide-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n}\n\n.slide-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.slide-panel-close[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.slide-panel-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n.search-box[_ngcontent-%COMP%] {\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 8px 12px;\n transition: all var(--mj-transition-base);\n}\n\n.search-input-wrapper[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n outline: none;\n background: transparent;\n font-size: 14px;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n\n.group-selector[_ngcontent-%COMP%] {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.group-selector[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-medium);\n white-space: nowrap;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.group-selector[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.new-group-input[_ngcontent-%COMP%] {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n\n.panel-results[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n}\n\n.panel-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.panel-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n\n\n\n\n\n\n.panel-app-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px 6px 12px;\n margin-top: 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.panel-app-header[_ngcontent-%COMP%]:first-child {\n margin-top: 0;\n}\n\n.panel-app-icon[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-app-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--panel-app-color);\n}\n\n.panel-app-name[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n\n.panel-item.panel-nav-item[_ngcontent-%COMP%] {\n padding: 10px 12px 10px 32px;\n margin-left: 12px;\n border-left: 2px solid var(--mj-border-subtle);\n}\n\n.panel-item.panel-nav-item[_ngcontent-%COMP%]:last-of-type {\n border-left-color: transparent;\n}\n\n.panel-item.panel-nav-item[_ngcontent-%COMP%]:hover {\n border-left-color: var(--mj-brand-primary);\n}\n\n\n.new-group-row[_ngcontent-%COMP%] {\n padding: 0 20px 12px 20px;\n}\n\n.new-group-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n.panel-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: var(--mj-radius-md);\n transition: all var(--mj-transition-base);\n cursor: pointer;\n}\n\n.panel-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.panel-item-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.panel-item-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.panel-item-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.panel-item-sub[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.panel-item-action[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.panel-item-action[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n padding: 4px 12px;\n border-radius: var(--mj-radius-sm);\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.pin-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.pin-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.pinned-badge[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-status-success);\n border: 1px solid var(--mj-status-success);\n cursor: default !important;\n}\n\n\n\n\n\n\n\n@media (max-width: 1200px) {\n .quick-access-sidebar[_ngcontent-%COMP%] {\n width: 280px;\n }\n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 280px;\n }\n\n .apps-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n }\n}\n\n\n@media (max-width: 992px) {\n .main-content[_ngcontent-%COMP%] {\n padding: 24px;\n }\n\n .greeting-section[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: var(--mj-text-3xl);\n }\n\n \n .quick-access-sidebar[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n }\n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 0;\n }\n\n \n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 320px;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n }\n}\n\n\n@media (max-width: 768px) {\n \n\n\n\n .main-content[_ngcontent-%COMP%] {\n padding: 20px;\n padding-bottom: 100px; \n }\n\n .home-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n margin-bottom: 24px;\n }\n\n .greeting-section[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: var(--mj-text-2xl);\n }\n\n \n .quick-access-sidebar[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 10000;\n border-left: none;\n border-top: none;\n }\n\n \n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::before {\n display: none;\n }\n\n \n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::after {\n display: none;\n }\n\n .pin-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 12px;\n }\n\n .slide-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .apps-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .app-card[_ngcontent-%COMP%] {\n padding: 16px;\n }\n\n .app-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n }\n\n .app-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n }\n\n .app-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n }\n\n .nav-preview[_ngcontent-%COMP%] {\n display: none;\n }\n\n \n .sidebar-fab-toggle[_ngcontent-%COMP%] {\n position: fixed;\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: var(--mj-text-lg);\n }\n}\n\n@media (max-width: 480px) {\n .main-content[_ngcontent-%COMP%] {\n padding: 16px;\n padding-bottom: 80px;\n }\n\n .greeting-section[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xl);\n }\n\n .greeting-section[_ngcontent-%COMP%] .date[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n }\n\n .section-title[_ngcontent-%COMP%] {\n font-size: var(--mj-text-base);\n margin-bottom: 16px;\n }\n\n .sidebar-fab-toggle[_ngcontent-%COMP%] {\n bottom: 16px;\n right: 16px;\n width: 44px;\n height: 44px;\n font-size: var(--mj-text-base);\n }\n}"], changeDetection: 0 });
|
|
3670
|
+
} }, dependencies: [i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.MJButtonDirective, i4.MJClickableDirective, i4.MJEmptyStateComponent, i4.MJAccordionPanelComponent, i4.MJAccordionTitleDirective, i4.MJAccordionActionsDirective, i4.MJAccordionBodyDirective, i5.LoadingComponent, i6.UserAppConfigComponent, i7.DashboardNameDialogComponent, i8.HomeDashboardSwitcherComponent, i9.ActionPinConfigDialogComponent, i10.ActionPinRunnerDialogComponent, i11.DashboardEditorComponent, i12.SlicePipe], styles: [".home-dashboard[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n position: relative;\n}\n\n\n.main-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow-y: auto;\n transition: margin-right var(--mj-transition-slow);\n}\n\n\n.home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 320px;\n}\n\n\n.home-overview[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 1180px;\n margin: 0 auto;\n padding: var(--mj-space-7) var(--mj-space-8) var(--mj-space-10);\n}\n\n\n.home-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-end;\n gap: var(--mj-space-4);\n margin-bottom: var(--mj-space-6);\n}\n\n.greeting-section[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-2xl);\n font-weight: var(--mj-font-bold);\n letter-spacing: var(--mj-tracking-tight);\n line-height: var(--mj-leading-tight);\n color: var(--mj-text-primary);\n}\n\n.greeting-section[_ngcontent-%COMP%] .date[_ngcontent-%COMP%] {\n margin: var(--mj-space-1) 0 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-muted);\n}\n\n\n\n\n\n\n.home-dashboard-view[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 520px;\n}\n\n\n.dashboard-title[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.dashboard-crumb[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.crumb-home[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 0;\n border: 0;\n background: transparent;\n font: inherit;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-link);\n cursor: pointer;\n}\n\n.crumb-home[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-link-hover);\n}\n\n.crumb-home[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n border-radius: var(--mj-radius-sm);\n box-shadow: var(--mj-focus-ring);\n}\n\n\n.sidebar-fab-toggle[_ngcontent-%COMP%] {\n position: absolute;\n top: 20px;\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: var(--mj-radius-full);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xl);\n cursor: pointer;\n box-shadow: var(--mj-shadow-brand-md);\n transition: all var(--mj-transition-base);\n z-index: 100;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sidebar-fab-toggle[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n box-shadow: 0 6px 16px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.fab-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n gap: 16px;\n color: var(--mj-text-muted);\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n font-size: var(--mj-text-4xl);\n color: var(--mj-brand-primary);\n}\n\n\n.apps-section[_ngcontent-%COMP%] {\n margin-bottom: var(--mj-space-8);\n}\n\n.section-title[_ngcontent-%COMP%] {\n margin: 0 0 var(--mj-space-3);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-bold);\n color: var(--mj-text-primary);\n}\n\n.apps-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));\n gap: var(--mj-space-3);\n}\n\n\n.app-card[_ngcontent-%COMP%] {\n --app-color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-3);\n padding: var(--mj-space-4);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition:\n border-color var(--mj-transition-fast),\n box-shadow var(--mj-transition-fast),\n transform var(--mj-transition-fast);\n}\n\n.app-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.app-card[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n box-shadow: var(--mj-focus-ring);\n}\n\n.app-icon[_ngcontent-%COMP%] {\n flex: 0 0 36px;\n display: grid;\n place-items: center;\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--app-color) 12%, transparent);\n color: var(--app-color);\n font-size: 16px;\n}\n\n.app-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.app-name[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.app-description[_ngcontent-%COMP%] {\n margin: 2px 0 0;\n font-size: var(--mj-text-xs);\n line-height: var(--mj-leading-snug);\n color: var(--mj-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n\n\n\n.quick-access-sidebar[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform var(--mj-transition-slow);\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.home-dashboard.sidebar-open[_ngcontent-%COMP%] .quick-access-sidebar[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.sidebar-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.sidebar-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sidebar-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n.sidebar-close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.sidebar-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n\n.sidebar-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.sidebar-section[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.sidebar-section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 12px 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n}\n\n.notifications-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-600);\n}\n\n.favorites-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.recents-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.section-badge[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: var(--mj-font-semibold);\n padding: 2px 6px;\n border-radius: var(--mj-radius-md);\n margin-left: auto;\n}\n\n\n.sidebar-items[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sidebar-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.sidebar-item-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n}\n\n.notification-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: var(--mj-color-warning-50);\n}\n\n.notification-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-600);\n}\n\n.favorite-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: var(--mj-color-warning-50);\n}\n\n.favorite-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.recent-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: var(--mj-color-info-50);\n}\n\n.recent-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-item-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.sidebar-item-title[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n padding: 8px 0;\n}\n\n.sidebar-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.sidebar-empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-4xl);\n margin-bottom: 12px;\n}\n\n.sidebar-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n}\n\n\n\n\n\n\n.pinned-section[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: var(--mj-space-8);\n}\n\n\n.pinned-title[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-bold);\n}\n\n.pinned-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n}\n\n\n.pinned-body[_ngcontent-%COMP%] {\n padding-top: var(--mj-space-3);\n}\n\n\n.edit-mode-banner[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n border-radius: var(--mj-radius-lg);\n padding: 12px 20px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.edit-mode-banner[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-base);\n}\n\n.edit-mode-banner[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n\n.pin-empty-state[_ngcontent-%COMP%] {\n position: relative;\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n border: 2px dashed var(--mj-border-default);\n}\n\n.pin-empty-close[_ngcontent-%COMP%] {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: var(--mj-text-sm);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.pin-empty-close[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n\n.pin-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: var(--mj-space-4);\n margin-bottom: var(--mj-space-3);\n}\n\n\n.group-header[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0 4px 0;\n margin-top: 8px;\n}\n\n.group-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.group-line[_ngcontent-%COMP%] {\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.group-count[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-disabled);\n background: var(--mj-bg-surface-card);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.group-name-input[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n padding: 2px 8px;\n background: var(--mj-bg-surface);\n outline: none;\n width: 160px;\n}\n\n.group-edit-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n}\n\n.group-edit-btn[_ngcontent-%COMP%] {\n background: none;\n border: 1px solid transparent;\n color: var(--mj-text-muted);\n font-size: 11px;\n cursor: pointer;\n padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all var(--mj-transition-base);\n}\n\n.group-edit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-default);\n color: var(--mj-text-secondary);\n}\n\n.group-edit-btn.danger[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n\n.pin-card[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n cursor: pointer;\n transition:\n border-color var(--mj-transition-fast),\n box-shadow var(--mj-transition-fast),\n transform var(--mj-transition-fast);\n}\n\n.pin-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.pin-card.edit-mode[_ngcontent-%COMP%] {\n cursor: grab;\n}\n\n.pin-card.edit-mode[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.pin-card.dragging[_ngcontent-%COMP%] {\n opacity: 0.5;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-lg);\n transform: rotate(2deg);\n}\n\n.pin-card.drag-over[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n\n.edit-controls[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n left: 8px;\n right: 8px;\n display: flex;\n justify-content: space-between;\n z-index: 10;\n pointer-events: none;\n}\n\n.edit-controls[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] {\n pointer-events: auto;\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n cursor: grab;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.drag-handle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.edit-card-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.edit-card-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-btn.delete[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n}\n\n\n.pin-thumbnail[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n aspect-ratio: 16 / 10;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.pin-thumbnail[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n\n.pin-thumbnail.icon-mode[_ngcontent-%COMP%] {\n display: grid;\n place-items: center;\n}\n\n.pin-thumbnail.icon-mode[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n display: grid;\n place-items: center;\n width: 52px;\n height: 52px;\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 22px;\n}\n\n\n.pin-thumbnail.action-mode[_ngcontent-%COMP%] {\n display: grid;\n place-items: center;\n background: var(--mj-brand-primary);\n}\n\n.pin-thumbnail.action-mode[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n font-size: 36px;\n color: var(--mj-text-inverse, white);\n}\n\n\n.pin-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n background: var(--mj-bg-overlay);\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--mj-transition-fast);\n}\n\n.pin-card[_ngcontent-%COMP%]:hover .pin-overlay[_ngcontent-%COMP%], \n.pin-card[_ngcontent-%COMP%]:focus-within .pin-overlay[_ngcontent-%COMP%] {\n opacity: 1;\n pointer-events: auto;\n}\n\n\n.pin-info[_ngcontent-%COMP%] {\n padding: var(--mj-space-3);\n}\n\n.pin-name[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1);\n min-width: 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.pin-name-text[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%] {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: 24px;\n height: 24px;\n margin: -4px -4px -4px 0;\n padding: 0;\n border: none;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 14px;\n cursor: pointer;\n opacity: 0;\n transition:\n opacity var(--mj-transition-fast),\n background-color var(--mj-transition-fast),\n color var(--mj-transition-fast);\n}\n\n\n.pin-card[_ngcontent-%COMP%]:hover .more-btn[_ngcontent-%COMP%], \n.pin-card[_ngcontent-%COMP%]:focus-within .more-btn[_ngcontent-%COMP%], \n.pin-card.menu-open[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%]:hover, \n.pin-card.menu-open[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.pin-name[_ngcontent-%COMP%] .more-btn[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n box-shadow: var(--mj-focus-ring);\n}\n\n.pin-name-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 2px 6px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n outline: none;\n background: var(--mj-bg-surface);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n\n.pin-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n min-width: 0;\n margin-top: 2px;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.pin-meta[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.pin-kind[_ngcontent-%COMP%] {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pin-card[_ngcontent-%COMP%], \n .app-card[_ngcontent-%COMP%] {\n transition: none;\n }\n .pin-card[_ngcontent-%COMP%]:hover, \n .app-card[_ngcontent-%COMP%]:hover {\n transform: none;\n }\n}\n\n\n.add-pin-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-lg);\n border: 2px dashed var(--mj-border-default);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 180px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n gap: 8px;\n color: var(--mj-text-muted);\n}\n\n.add-pin-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-pin-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n}\n\n.add-pin-card[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n}\n\n\n\n\n\n.pin-context-menu[_ngcontent-%COMP%] {\n position: fixed;\n z-index: 10001;\n width: 220px;\n overflow-y: auto;\n padding: 6px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n animation: _ngcontent-%COMP%_pinMenuIn var(--mj-transition-fast);\n}\n\n@keyframes _ngcontent-%COMP%_pinMenuIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-context-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3);\n width: 100%;\n padding: 8px 10px;\n border: 0;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n font: inherit;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n text-align: left;\n cursor: pointer;\n}\n\n.pin-context-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n.pin-context-item[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n background: var(--mj-bg-surface-hover);\n box-shadow: inset 0 0 0 var(--mj-ring-width) var(--mj-focus-ring-color);\n}\n\n.pin-context-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 14px;\n text-align: center;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.pin-context-item.danger[_ngcontent-%COMP%], \n.pin-context-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.pin-context-item.submenu-header[_ngcontent-%COMP%] {\n padding-bottom: 4px;\n cursor: default;\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n}\n\n.pin-context-item.submenu-header[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n.pin-context-item.submenu-item[_ngcontent-%COMP%] {\n padding-left: 34px;\n}\n\n.pin-context-divider[_ngcontent-%COMP%] {\n height: 1px;\n margin: 6px 4px;\n background: var(--mj-border-default);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pin-context-menu[_ngcontent-%COMP%] { animation: none; }\n}\n\n\n\n\n.slide-panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 2000;\n}\n\n.slide-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 400px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-xl);\n z-index: 2001;\n display: flex;\n flex-direction: column;\n animation: _ngcontent-%COMP%_slideIn 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideIn {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n.slide-panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.slide-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n}\n\n.slide-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.slide-panel-close[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.slide-panel-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n.search-box[_ngcontent-%COMP%] {\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 8px 12px;\n transition: all var(--mj-transition-base);\n}\n\n.search-input-wrapper[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n border: none;\n outline: none;\n background: transparent;\n font-size: 14px;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n}\n\n\n.group-selector[_ngcontent-%COMP%] {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.group-selector[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-medium);\n white-space: nowrap;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.group-selector[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.new-group-input[_ngcontent-%COMP%] {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n\n.panel-results[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n}\n\n.panel-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.panel-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n\n\n\n\n\n\n.panel-app-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px 6px 12px;\n margin-top: 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.panel-app-header[_ngcontent-%COMP%]:first-child {\n margin-top: 0;\n}\n\n.panel-app-icon[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-app-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--panel-app-color);\n}\n\n.panel-app-name[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n\n.panel-item.panel-nav-item[_ngcontent-%COMP%] {\n padding: 10px 12px 10px 32px;\n margin-left: 12px;\n border-left: 2px solid var(--mj-border-subtle);\n}\n\n.panel-item.panel-nav-item[_ngcontent-%COMP%]:last-of-type {\n border-left-color: transparent;\n}\n\n.panel-item.panel-nav-item[_ngcontent-%COMP%]:hover {\n border-left-color: var(--mj-brand-primary);\n}\n\n\n.new-group-row[_ngcontent-%COMP%] {\n padding: 0 20px 12px 20px;\n}\n\n.new-group-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n.panel-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: var(--mj-radius-md);\n transition: all var(--mj-transition-base);\n cursor: pointer;\n}\n\n.panel-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.panel-item-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.panel-item-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.panel-item-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.panel-item-sub[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.panel-item-action[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.panel-item-action[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n padding: 4px 12px;\n border-radius: var(--mj-radius-sm);\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.pin-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.pin-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.pinned-badge[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-status-success);\n border: 1px solid var(--mj-status-success);\n cursor: default !important;\n}\n\n\n\n\n\n\n\n@media (max-width: 1200px) {\n .quick-access-sidebar[_ngcontent-%COMP%] {\n width: 280px;\n }\n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 280px;\n }\n}\n\n\n@media (max-width: 992px) {\n \n .quick-access-sidebar[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n }\n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 0;\n }\n\n \n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 320px;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n }\n}\n\n\n@media (max-width: 900px) {\n .home-overview[_ngcontent-%COMP%] {\n padding: var(--mj-space-5) var(--mj-space-4);\n }\n}\n\n\n@media (max-width: 768px) {\n .home-overview[_ngcontent-%COMP%] {\n padding-bottom: 100px; \n }\n\n \n .quick-access-sidebar[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 10000;\n border-left: none;\n border-top: none;\n }\n\n \n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::before {\n display: none;\n }\n\n \n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::after {\n display: none;\n }\n\n .pin-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: var(--mj-space-3);\n }\n\n .slide-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n \n .sidebar-fab-toggle[_ngcontent-%COMP%] {\n position: fixed;\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: var(--mj-text-lg);\n }\n}\n\n@media (max-width: 480px) {\n .home-overview[_ngcontent-%COMP%] {\n padding-bottom: 80px;\n }\n\n .greeting-section[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xl);\n }\n\n .greeting-section[_ngcontent-%COMP%] .date[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n }\n\n \n\n .pinned-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n display: none;\n }\n\n .pinned-actions[_ngcontent-%COMP%] .pin-action-label[_ngcontent-%COMP%] {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n\n .sidebar-fab-toggle[_ngcontent-%COMP%] {\n bottom: 16px;\n right: 16px;\n width: 44px;\n height: 44px;\n font-size: var(--mj-text-base);\n }\n}"], changeDetection: 0 });
|
|
2996
3671
|
};
|
|
2997
3672
|
HomeDashboardComponent = __decorate([
|
|
2998
3673
|
RegisterClass(BaseResourceComponent, 'HomeDashboard')
|
|
@@ -3000,10 +3675,23 @@ HomeDashboardComponent = __decorate([
|
|
|
3000
3675
|
export { HomeDashboardComponent };
|
|
3001
3676
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(HomeDashboardComponent, [{
|
|
3002
3677
|
type: Component,
|
|
3003
|
-
args: [{ standalone: false, selector: 'mj-home-dashboard', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"home-dashboard\" [class.sidebar-open]=\"sidebarOpen && hasSidebarContent\">\n <!-- Main Content Area -->\n <div class=\"main-content\">\n <!-- Header Section -->\n <div class=\"home-header\">\n <div class=\"greeting-section\">\n <h1>{{ greeting }}, {{ currentUser?.Name }}</h1>\n <p class=\"date\">{{ formattedDate }}</p>\n </div>\n </div>\n\n <!-- Pinned Section -->\n @if (!isLoading) {\n <div class=\"pinned-section\">\n <div class=\"pinned-header\">\n <h2 class=\"section-title\">\n <i class=\"fa-solid fa-thumbtack\"></i>\n Pinned\n </h2>\n <div class=\"pinned-actions\">\n @if (EditMode) {\n <button class=\"pin-action-btn done\" (click)=\"ToggleEditMode()\">\n <i class=\"fa-solid fa-check\"></i> Done\n </button>\n } @else {\n <button class=\"pin-action-btn primary\" (click)=\"OpenAddPinPanel()\">\n <i class=\"fa-solid fa-plus\"></i> Add Pin\n </button>\n @if (PinnedItems.length > 0) {\n <button class=\"pin-action-btn\" (click)=\"ToggleEditMode()\">\n <i class=\"fa-solid fa-pen\"></i> Edit\n </button>\n }\n }\n </div>\n </div>\n\n @if (EditMode) {\n <div class=\"edit-mode-banner\">\n <i class=\"fa-solid fa-arrows-up-down-left-right\"></i>\n <span><strong>Edit mode</strong> \u2014 Drag cards to reorder. Click names to rename.</span>\n </div>\n }\n\n <!-- Empty State -->\n @if (PinnedItems.length === 0 && (EditMode || !HidePinEmptyState)) {\n <div class=\"pin-empty-state\">\n @if (!EditMode) {\n <button type=\"button\" class=\"pin-empty-close\" (click)=\"DismissPinEmptyState()\" title=\"Hide this\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n }\n <mj-empty-state Icon=\"fa-solid fa-thumbtack\"\n Title=\"No pinned items yet\"\n Message=\"Pin your favorite dashboards, views, queries, and reports for quick access.\">\n <button actions mjButton variant=\"primary\" (click)=\"OpenAddPinPanel()\">\n <i class=\"fa-solid fa-plus\"></i> Add your first pin\n </button>\n @if (!EditMode && !HidePinEmptyState) {\n <button actions mjButton variant=\"flat\" (click)=\"DismissPinEmptyState()\">\n Don't show this again\n </button>\n }\n </mj-empty-state>\n </div>\n }\n\n <!-- Pin Grid -->\n @if (PinnedItems.length > 0) {\n <div class=\"pin-grid\">\n <!-- Ungrouped Pins -->\n @for (pin of UngroupedPins; track trackByPin($index, pin)) {\n <div class=\"pin-card\"\n [class.edit-mode]=\"EditMode\"\n [class.dragging]=\"DraggingPinId === pin.Id\"\n [class.drag-over]=\"DragOverPinId === pin.Id\"\n [draggable]=\"EditMode\"\n (dragstart)=\"OnDragStart($event, pin)\"\n (dragover)=\"OnDragOver($event, pin)\"\n (dragleave)=\"OnDragLeave()\"\n (drop)=\"OnDrop($event, pin)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"OnPinClick(pin)\">\n\n <!-- Edit mode controls -->\n @if (EditMode) {\n <div class=\"edit-controls\">\n <div class=\"drag-handle\"><i class=\"fa-solid fa-grip-vertical\"></i></div>\n <div class=\"edit-card-actions\">\n <button class=\"edit-card-btn delete\" aria-label=\"Remove pin\" title=\"Remove pin\" (click)=\"RemovePin(pin.Id); $event.stopPropagation()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n </div>\n }\n\n <!-- Thumbnail / Icon -->\n @if (pin.Thumbnail) {\n <div class=\"pin-thumbnail\">\n <img [src]=\"pin.Thumbnail\" [alt]=\"pin.DisplayName\" />\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button class=\"open-btn\" (click)=\"OnPinClick(pin); $event.stopPropagation()\">Open</button>\n </div>\n }\n </div>\n } @else if (pin.ResourceType === 'Actions') {\n <div class=\"pin-thumbnail action-mode\"\n [style.background]=\"'linear-gradient(135deg, ' + GetPinAccentColor(pin) + ' 0%, ' + GetPinAccentColor(pin) + 'cc 100%)'\">\n <i [class]=\"GetPinIcon(pin)\"></i>\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button class=\"open-btn\" (click)=\"OnPinClick(pin); $event.stopPropagation()\">Run</button>\n </div>\n }\n </div>\n } @else {\n <div class=\"pin-thumbnail icon-mode\" [style.--pin-icon-color]=\"pin.Color || 'var(--mj-text-muted)'\">\n <i [class]=\"GetPinIcon(pin)\"></i>\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button class=\"open-btn\" (click)=\"OnPinClick(pin); $event.stopPropagation()\">Open</button>\n </div>\n }\n </div>\n }\n\n <!-- Pin Info -->\n <div class=\"pin-info\">\n @if (EditMode && EditingPinId === pin.Id) {\n <input class=\"pin-name-input\"\n [value]=\"pin.DisplayName\"\n (blur)=\"SavePinName(pin.Id, GetInputValue($event))\"\n (keydown.enter)=\"SavePinName(pin.Id, GetInputValue($event))\"\n (click)=\"$event.stopPropagation()\" />\n } @else {\n <div class=\"pin-name\" (click)=\"EditMode ? StartEditingPin(pin.Id, $event) : null\">\n {{ pin.DisplayName }}\n @if (!EditMode) {\n <button class=\"more-btn\" aria-label=\"Pin options\" title=\"Pin options\" (click)=\"ShowPinMenu($event, pin)\">\n <i class=\"fa-solid fa-ellipsis\"></i>\n </button>\n }\n </div>\n }\n <div class=\"pin-meta\">\n <i [class]=\"GetPinIcon(pin)\"></i>\n {{ GetResourceTypeLabel(pin) }}\n @if (pin.ApplicationName && pin.ResourceType !== 'Custom') {\n <span class=\"pin-app-badge\">{{ pin.ApplicationName }}</span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Grouped Pins -->\n @for (group of PinGroups; track trackByGroup($index, group)) {\n <!-- Group Header -->\n <div class=\"group-header\">\n @if (EditMode && EditingGroupName === group) {\n <input class=\"group-name-input\"\n [value]=\"group\"\n (blur)=\"SaveGroupName(group, GetInputValue($event))\"\n (keydown.enter)=\"SaveGroupName(group, GetInputValue($event))\" />\n } @else {\n <span class=\"group-name\" (click)=\"EditMode ? StartEditingGroup(group) : null\">{{ group }}</span>\n }\n <div class=\"group-line\"></div>\n <span class=\"group-count\">{{ GetPinsInGroup(group).length }} pins</span>\n @if (EditMode) {\n <div class=\"group-edit-controls\">\n <button class=\"group-edit-btn danger\" (click)=\"RemoveGroup(group)\">\n <i class=\"fa-solid fa-folder-minus\"></i> Remove Group\n </button>\n </div>\n }\n </div>\n\n <!-- Pins in Group -->\n @for (pin of GetPinsInGroup(group); track trackByPin($index, pin)) {\n <div class=\"pin-card\"\n [class.edit-mode]=\"EditMode\"\n [class.dragging]=\"DraggingPinId === pin.Id\"\n [class.drag-over]=\"DragOverPinId === pin.Id\"\n [draggable]=\"EditMode\"\n (dragstart)=\"OnDragStart($event, pin)\"\n (dragover)=\"OnDragOver($event, pin)\"\n (dragleave)=\"OnDragLeave()\"\n (drop)=\"OnDrop($event, pin)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"OnPinClick(pin)\">\n\n @if (EditMode) {\n <div class=\"edit-controls\">\n <div class=\"drag-handle\"><i class=\"fa-solid fa-grip-vertical\"></i></div>\n <div class=\"edit-card-actions\">\n <button class=\"edit-card-btn delete\" aria-label=\"Remove pin\" title=\"Remove pin\" (click)=\"RemovePin(pin.Id); $event.stopPropagation()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n </div>\n }\n\n @if (pin.Thumbnail) {\n <div class=\"pin-thumbnail\">\n <img [src]=\"pin.Thumbnail\" [alt]=\"pin.DisplayName\" />\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button class=\"open-btn\" (click)=\"OnPinClick(pin); $event.stopPropagation()\">Open</button>\n </div>\n }\n </div>\n } @else if (pin.ResourceType === 'Actions') {\n <div class=\"pin-thumbnail action-mode\"\n [style.background]=\"'linear-gradient(135deg, ' + GetPinAccentColor(pin) + ' 0%, ' + GetPinAccentColor(pin) + 'cc 100%)'\">\n <i [class]=\"GetPinIcon(pin)\"></i>\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button class=\"open-btn\" (click)=\"OnPinClick(pin); $event.stopPropagation()\">Run</button>\n </div>\n }\n </div>\n } @else {\n <div class=\"pin-thumbnail icon-mode\" [style.--pin-icon-color]=\"pin.Color || 'var(--mj-text-muted)'\">\n <i [class]=\"GetPinIcon(pin)\"></i>\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button class=\"open-btn\" (click)=\"OnPinClick(pin); $event.stopPropagation()\">Open</button>\n </div>\n }\n </div>\n }\n\n <div class=\"pin-info\">\n @if (EditMode && EditingPinId === pin.Id) {\n <input class=\"pin-name-input\"\n [value]=\"pin.DisplayName\"\n (blur)=\"SavePinName(pin.Id, $event.target.value)\"\n (keydown.enter)=\"SavePinName(pin.Id, $event.target.value)\"\n (click)=\"$event.stopPropagation()\" />\n } @else {\n <div class=\"pin-name\" (click)=\"EditMode ? StartEditingPin(pin.Id, $event) : null\">\n {{ pin.DisplayName }}\n @if (!EditMode) {\n <button class=\"more-btn\" aria-label=\"Pin options\" title=\"Pin options\" (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-ellipsis\"></i>\n </button>\n }\n </div>\n }\n <div class=\"pin-meta\">\n <i [class]=\"GetPinIcon(pin)\"></i>\n {{ GetResourceTypeLabel(pin) }}\n @if (pin.ApplicationName) {\n <span class=\"pin-app-badge\">{{ pin.ApplicationName }}</span>\n }\n </div>\n </div>\n </div>\n }\n }\n\n <!-- Add Pin card (edit mode) -->\n @if (EditMode) {\n <div class=\"add-pin-card\" (click)=\"OpenAddPinPanel()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Add Pin</span>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- Pin Context Menu (ellipsis) -->\n @if (PinMenuVisible && PinMenuPin) {\n <div class=\"pin-context-menu\"\n [style.left.px]=\"PinMenuX\"\n [style.top.px]=\"PinMenuY\">\n <div class=\"pin-context-item\" (click)=\"OnPinMenuEdit()\">\n <i class=\"fa-solid fa-pen\"></i>\n <span>Edit</span>\n </div>\n <div class=\"pin-context-divider\"></div>\n <div class=\"pin-context-submenu\">\n <div class=\"pin-context-item submenu-header\">\n <i class=\"fa-solid fa-folder\"></i>\n <span>Move to Group</span>\n </div>\n @if (PinMenuPin.Group) {\n <div class=\"pin-context-item submenu-item\" (click)=\"OnPinMenuMoveToGroup(undefined)\">\n <span>(No group)</span>\n </div>\n }\n @for (group of PinGroups; track group) {\n @if (group !== PinMenuPin.Group) {\n <div class=\"pin-context-item submenu-item\" (click)=\"OnPinMenuMoveToGroup(group)\">\n <span>{{ group }}</span>\n </div>\n }\n }\n </div>\n <div class=\"pin-context-divider\"></div>\n <div class=\"pin-context-item danger\" (click)=\"OnPinMenuUnpin()\">\n <i class=\"fa-solid fa-thumbtack-slash\"></i>\n <span>Unpin</span>\n </div>\n </div>\n }\n\n <!-- Add Pin Slide-In Panel -->\n @if (AddPanelOpen) {\n <div class=\"slide-panel-backdrop\" (click)=\"CloseAddPinPanel()\"></div>\n <div class=\"slide-panel\">\n <div class=\"slide-panel-header\">\n <h3><i class=\"fa-solid fa-thumbtack\"></i> Add Pin</h3>\n <button class=\"slide-panel-close\" (click)=\"CloseAddPinPanel()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <div class=\"search-box\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <input type=\"text\"\n placeholder=\"Search apps, dashboards, views, queries...\"\n [(ngModel)]=\"AddPanelSearchQuery\" />\n </div>\n </div>\n\n <div class=\"group-selector\">\n <label><i class=\"fa-solid fa-folder\"></i> Add to group:</label>\n <select [(ngModel)]=\"AddPanelSelectedGroup\">\n <option value=\"\">(No group)</option>\n @for (group of PinGroups; track group) {\n <option [value]=\"group\">{{ group }}</option>\n }\n <option value=\"__new__\">+ New group...</option>\n </select>\n </div>\n @if (AddPanelSelectedGroup === '__new__') {\n <div class=\"new-group-row\">\n <input class=\"new-group-input\"\n type=\"text\"\n placeholder=\"Enter new group name...\"\n [(ngModel)]=\"AddPanelNewGroupName\" />\n </div>\n }\n\n <div class=\"panel-results\">\n @if (AddPanelLoading) {\n <div class=\"panel-loading\">\n <mj-loading text=\"Loading resources...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n <!-- Apps with Nav Items -->\n @if (FilterApps().length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['apps']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('apps', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-grid-2\"></i> Applications\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterApps().length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (app of FilterApps(); track app.appId) {\n <div class=\"panel-app-header\" [style.--panel-app-color]=\"app.color\">\n <div class=\"panel-app-icon\">\n <i [class]=\"app.icon\"></i>\n </div>\n <span class=\"panel-app-name\">{{ app.appName }}</span>\n </div>\n @for (ni of app.navItems; track ni.label) {\n <div class=\"panel-item panel-nav-item\">\n <div class=\"panel-item-icon\" [style.background]=\"'color-mix(in srgb, ' + app.color + ' 10%, var(--mj-bg-surface-card))'\">\n <i [class]=\"ni.icon\" [style.color]=\"app.color\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ ni.label }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (ni.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinAppNavItem(app.appName, app.icon, app.color, ni.label, ni.icon)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Dashboards (metadata-driven Config type only) -->\n @if (FilterPanelItems(AvailableDashboards).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['dashboards']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('dashboards', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-gauge-high\"></i> Dashboards\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableDashboards).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableDashboards); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-gauge-high\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (item.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinFromPanel('Dashboards', item.id, item.name)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Views -->\n @if (FilterPanelItems(AvailableViews).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['views']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('views', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-table-list\"></i> Views\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableViews).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableViews); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-table-list\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n <div class=\"panel-item-sub\">{{ item.entityName }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (item.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinFromPanel('User Views', item.id, item.name)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Queries -->\n @if (FilterPanelItems(AvailableQueries).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['queries']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('queries', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-database\"></i> Queries\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableQueries).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableQueries); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-database\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (item.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinFromPanel('Queries', item.id, item.name)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Quick Actions -->\n @if (FilterPanelItems(AvailableActions).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['actions']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('actions', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-bolt\"></i> Quick Actions\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableActions).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableActions); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-bolt\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n @if (item.description) {\n <div class=\"panel-item-sub\">{{ item.description }}</div>\n }\n </div>\n <div class=\"panel-item-action\">\n <button class=\"pin-btn\" (click)=\"OpenActionPinConfig(item.id, item.name, item.description)\">\n <i class=\"fa-solid fa-sliders\"></i> Configure\n </button>\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n }\n </div>\n </div>\n }\n\n <!-- Action Pin Dialogs -->\n <mj-action-pin-config-dialog\n [Visible]=\"ActionConfigDialogVisible\"\n [ActionID]=\"ActionConfigActionId\"\n [ActionName]=\"ActionConfigActionName\"\n [ActionDescription]=\"ActionConfigActionDescription\"\n (Result)=\"OnActionConfigResult($event)\">\n </mj-action-pin-config-dialog>\n\n <mj-action-pin-runner-dialog\n [Visible]=\"ActionRunnerDialogVisible\"\n [Pin]=\"ActionRunnerPin\"\n (Result)=\"OnActionRunnerResult($event)\">\n </mj-action-pin-runner-dialog>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading your applications...\" size=\"large\"></mj-loading>\n </div>\n }\n\n <!-- Apps Grid -->\n @if (!isLoading) {\n <div class=\"apps-section\">\n <h2 class=\"section-title\">\n <i class=\"fa-solid fa-grid-2\"></i>\n My Applications\n </h2>\n <div class=\"apps-grid\">\n @for (appData of appsDisplayData; track trackByApp($index, appData)) {\n <div\n class=\"app-card\"\n [mjClickable]=\"appData.app.Name\"\n [testId]=\"'app-tile-' + appData.app.Name\"\n [style.--app-color]=\"appData.color\"\n (click)=\"onAppClick(appData.app)\">\n <!-- App Icon -->\n <div class=\"app-icon-wrapper\">\n <div class=\"app-icon\">\n <i [class]=\"appData.icon\"></i>\n </div>\n </div>\n <!-- App Info -->\n <div class=\"app-info\">\n <h3 class=\"app-name\">{{ appData.app.Name }}</h3>\n @if (appData.app.Description) {\n <p class=\"app-description\">{{ appData.app.Description }}</p>\n }\n <!-- Nav Items Preview -->\n @if (appData.navItemsCount > 0) {\n <div class=\"nav-preview\">\n @for (item of appData.navItemsPreview; track trackByNavItem($index, item)) {\n <div class=\"nav-item-chip\">\n <i [class]=\"item.Icon\"></i>\n <span>{{ item.Label }}</span>\n </div>\n }\n @if (appData.showMoreItems) {\n <span class=\"more-items\">\n +{{ appData.moreItemsCount }} more\n </span>\n }\n </div>\n }\n </div>\n <!-- Hover Arrow -->\n <div class=\"app-arrow\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n }\n </div>\n <!-- Empty State -->\n @if (apps.length === 0) {\n <mj-empty-state Icon=\"fa-solid fa-folder-open\"\n Title=\"No Applications Available\"\n Message=\"You don't have any applications configured yet.\"\n ActionText=\"Configure Applications\"\n ActionIcon=\"fa-solid fa-gear\"\n (Action)=\"openConfigDialog()\" />\n }\n </div>\n }\n </div>\n\n <!-- Collapsible Right Sidebar -->\n @if (hasSidebarContent) {\n <div class=\"quick-access-sidebar\">\n <div class=\"sidebar-header\">\n <h3>\n <i class=\"fa-solid fa-bolt\"></i>\n Quick Access\n </h3>\n <button class=\"sidebar-close-btn\" (click)=\"toggleSidebar()\" title=\"Close panel\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"sidebar-content\">\n <!-- Unread Notifications Section -->\n @if (unreadNotifications.length > 0) {\n <div class=\"sidebar-section notifications-section\">\n <h4 class=\"sidebar-section-title\">\n <i class=\"fa-solid fa-bell\"></i>\n Notifications\n <span class=\"section-badge\">{{ unreadNotifications.length }}</span>\n </h4>\n <div class=\"sidebar-items\">\n @for (notification of unreadNotifications; track trackByNotification($index, notification)) {\n <div\n class=\"sidebar-item notification-item\"\n [mjClickable]=\"notification.Title\"\n testId=\"notification-item\"\n (click)=\"onNotificationClick(notification)\">\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ notification.Title }}</span>\n <span class=\"sidebar-item-subtitle\">{{ notification.Message | slice:0:40 }}{{ (notification.Message?.length || 0) > 40 ? '...' : '' }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Favorites Section -->\n @if (favorites.length > 0 || favoritesLoading) {\n <div class=\"sidebar-section favorites-section\">\n <h4 class=\"sidebar-section-title\">\n <i class=\"fa-solid fa-star\"></i>\n Favorites\n </h4>\n @if (!favoritesLoading) {\n <div class=\"sidebar-items\">\n @for (favorite of favorites; track trackByFavorite($index, favorite)) {\n <div\n class=\"sidebar-item favorite-item\"\n [mjClickable]=\"getFavoriteDisplayName(favorite)\"\n testId=\"favorite-item\"\n (click)=\"onFavoriteClick(favorite)\">\n <div class=\"sidebar-item-icon\">\n <i [class]=\"getEntityIconByName(favorite.Entity)\"></i>\n </div>\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ getFavoriteDisplayName(favorite) }}</span>\n <span class=\"sidebar-item-subtitle\">{{ favorite.Entity }}</span>\n </div>\n </div>\n }\n </div>\n }\n @if (favoritesLoading) {\n <div class=\"sidebar-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading...</span>\n </div>\n }\n </div>\n }\n <!-- Recents Section -->\n @if (recentItems.length > 0 || recentsLoading) {\n <div class=\"sidebar-section recents-section\">\n <h4 class=\"sidebar-section-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n Recent\n </h4>\n @if (!recentsLoading) {\n <div class=\"sidebar-items\">\n @for (item of recentItems; track trackByRecent($index, item)) {\n <div\n class=\"sidebar-item recent-item\"\n [mjClickable]=\"item.recordName || item.recordId\"\n testId=\"recent-item\"\n (click)=\"onRecentClick(item)\">\n <div class=\"sidebar-item-icon\">\n <i [class]=\"getEntityIconByName(item.entityName)\"></i>\n </div>\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ item.recordName || item.recordId }}</span>\n <span class=\"sidebar-item-subtitle\">{{ item.entityName }} \u00B7 {{ formatDate(item.latestAt) }}</span>\n </div>\n </div>\n }\n </div>\n }\n @if (recentsLoading) {\n <div class=\"sidebar-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading...</span>\n </div>\n }\n </div>\n }\n <!-- Empty sidebar state -->\n @if (!favoritesLoading && !recentsLoading && unreadNotifications.length === 0 && favorites.length === 0 && recentItems.length === 0) {\n <mj-empty-state class=\"sidebar-empty\" Size=\"compact\"\n Icon=\"fa-solid fa-inbox\"\n Title=\"No quick access items\" />\n }\n </div>\n </div>\n }\n\n <!-- Quick Access FAB Toggle (Fixed Button) -->\n @if (hasSidebarContent && !sidebarOpen) {\n <button class=\"sidebar-fab-toggle\"\n (click)=\"toggleSidebar()\"\n title=\"Quick Access\">\n <i class=\"fa-solid fa-bolt\"></i>\n @if (unreadNotifications.length > 0) {\n <span class=\"fab-badge\">{{ unreadNotifications.length }}</span>\n }\n </button>\n }\n\n <!-- App Configuration Dialog -->\n <mj-user-app-config\n #appConfigDialog\n [(ShowDialog)]=\"showConfigDialog\"\n (ConfigSaved)=\"onConfigSaved()\">\n </mj-user-app-config>\n</div>\n", styles: [".home-dashboard {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n position: relative;\n}\n\n/* Main Content Area */\n.main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 32px;\n overflow-y: auto;\n transition: margin-right var(--mj-transition-slow);\n}\n\n/* Sidebar open state adjusts main content on desktop */\n.home-dashboard.sidebar-open .main-content {\n margin-right: 320px;\n}\n\n/* Header */\n.home-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 32px;\n}\n\n.greeting-section h1 {\n margin: 0 0 8px 0;\n font-size: var(--mj-text-4xl);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.greeting-section .date {\n margin: 0;\n font-size: var(--mj-text-base);\n color: var(--mj-text-muted);\n}\n\n/* FAB Toggle Button for Quick Access - top-right on desktop */\n.sidebar-fab-toggle {\n position: absolute;\n top: 20px;\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: var(--mj-radius-full);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xl);\n cursor: pointer;\n box-shadow: var(--mj-shadow-brand-md);\n transition: all var(--mj-transition-base);\n z-index: 100;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sidebar-fab-toggle:hover {\n background: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n box-shadow: 0 6px 16px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Loading State */\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n gap: 16px;\n color: var(--mj-text-muted);\n}\n\n.loading-spinner {\n font-size: var(--mj-text-4xl);\n color: var(--mj-brand-primary);\n}\n\n/* Apps Section */\n.apps-section {\n flex: 0 0 auto;\n}\n\n.section-title {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0 0 24px 0;\n font-size: var(--mj-text-xl);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n.section-title i {\n color: var(--mj-text-muted);\n}\n\n/* Apps Grid */\n.apps-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 20px;\n}\n\n/* App Card */\n.app-card {\n --app-color: var(--mj-text-muted);\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition: all 0.25s ease;\n position: relative;\n overflow: hidden;\n}\n\n.app-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n background: var(--app-color);\n opacity: 0;\n transition: opacity 0.25s ease;\n}\n\n.app-card:hover {\n border-color: var(--app-color);\n box-shadow: var(--mj-shadow-lg);\n transform: translateY(-3px);\n}\n\n.app-card:hover::before {\n opacity: 1;\n}\n\n/* App Icon */\n.app-icon-wrapper {\n flex-shrink: 0;\n}\n\n.app-icon {\n width: 52px;\n height: 52px;\n border-radius: var(--mj-radius-lg);\n background: color-mix(in srgb, var(--app-color) 12%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.25s ease;\n}\n\n.app-icon i {\n font-size: var(--mj-text-xl);\n color: var(--app-color);\n transition: transform 0.25s ease;\n}\n\n.app-card:hover .app-icon {\n background: var(--app-color);\n}\n\n.app-card:hover .app-icon i {\n color: var(--mj-text-inverse);\n transform: scale(1.1);\n}\n\n/* App Info */\n.app-info {\n flex: 1;\n min-width: 0;\n}\n\n.app-name {\n margin: 0 0 4px 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.app-description {\n margin: 0 0 10px 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n line-height: var(--mj-leading-snug);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Nav Items Preview */\n.nav-preview {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n}\n\n.nav-item-chip {\n display: flex;\n align-items: center;\n gap: 5px;\n padding: 3px 8px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n}\n\n.nav-item-chip i {\n font-size: 9px;\n color: var(--mj-text-muted);\n}\n\n.more-items {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* App Arrow */\n.app-arrow {\n position: absolute;\n right: 14px;\n top: 50%;\n transform: translateY(-50%) translateX(10px);\n opacity: 0;\n transition: all 0.25s ease;\n color: var(--app-color);\n font-size: var(--mj-text-base);\n}\n\n.app-card:hover .app-arrow {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n}\n\n/* ========================================\n RIGHT SIDEBAR\n ======================================== */\n.quick-access-sidebar {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform var(--mj-transition-slow);\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.home-dashboard.sidebar-open .quick-access-sidebar {\n transform: translateX(0);\n}\n\n.sidebar-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.sidebar-header h3 {\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sidebar-header h3 i {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n.sidebar-close-btn {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.sidebar-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n/* Sidebar Sections */\n.sidebar-section {\n margin-bottom: 20px;\n}\n\n.sidebar-section:last-child {\n margin-bottom: 0;\n}\n\n.sidebar-section-title {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 12px 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title i {\n font-size: var(--mj-text-xs);\n}\n\n.notifications-section .sidebar-section-title i {\n color: var(--mj-color-warning-600);\n}\n\n.favorites-section .sidebar-section-title i {\n color: var(--mj-status-warning);\n}\n\n.recents-section .sidebar-section-title i {\n color: var(--mj-brand-primary);\n}\n\n.section-badge {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: var(--mj-font-semibold);\n padding: 2px 6px;\n border-radius: var(--mj-radius-md);\n margin-left: auto;\n}\n\n/* Sidebar Items */\n.sidebar-items {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sidebar-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.sidebar-item-icon {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.sidebar-item-icon i {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n}\n\n.notification-item .sidebar-item-icon {\n background: var(--mj-color-warning-50);\n}\n\n.notification-item .sidebar-item-icon i {\n color: var(--mj-color-warning-600);\n}\n\n.favorite-item .sidebar-item-icon {\n background: var(--mj-color-warning-50);\n}\n\n.favorite-item .sidebar-item-icon i {\n color: var(--mj-color-warning-500);\n}\n\n.recent-item .sidebar-item-icon {\n background: var(--mj-color-info-50);\n}\n\n.recent-item .sidebar-item-icon i {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-item-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.sidebar-item-title {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n padding: 8px 0;\n}\n\n.sidebar-loading i {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.sidebar-empty i {\n font-size: var(--mj-text-4xl);\n margin-bottom: 12px;\n}\n\n.sidebar-empty p {\n margin: 0;\n font-size: var(--mj-text-sm);\n}\n\n\n/* ========================================\n PINNED SECTION\n ======================================== */\n.pinned-section {\n margin-bottom: 32px;\n}\n\n.pinned-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n}\n\n.pinned-header .section-title {\n margin: 0;\n}\n\n.pinned-actions {\n margin-left: auto;\n display: flex;\n gap: 8px;\n}\n\n.pin-action-btn {\n padding: 6px 14px;\n border-radius: var(--mj-radius-md);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all var(--mj-transition-base);\n}\n\n.pin-action-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.pin-action-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.pin-action-btn.primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.pin-action-btn.done {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-success);\n}\n\n/* Edit Mode Banner */\n.edit-mode-banner {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n border-radius: var(--mj-radius-lg);\n padding: 12px 20px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.edit-mode-banner i {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-base);\n}\n\n.edit-mode-banner strong {\n color: var(--mj-brand-primary);\n}\n\n/* Pin Empty State */\n.pin-empty-state {\n position: relative;\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n border: 2px dashed var(--mj-border-default);\n}\n\n.pin-empty-close {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: var(--mj-text-sm);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.pin-empty-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n/* Pin Grid */\n.pin-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 16px;\n margin-bottom: 12px;\n}\n\n/* Group Header */\n.group-header {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0 4px 0;\n margin-top: 8px;\n}\n\n.group-name {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.group-line {\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.group-count {\n font-size: 11px;\n color: var(--mj-text-disabled);\n background: var(--mj-bg-surface-card);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.group-name-input {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n padding: 2px 8px;\n background: var(--mj-bg-surface);\n outline: none;\n width: 160px;\n}\n\n.group-edit-controls {\n display: flex;\n gap: 6px;\n}\n\n.group-edit-btn {\n background: none;\n border: 1px solid transparent;\n color: var(--mj-text-muted);\n font-size: 11px;\n cursor: pointer;\n padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all var(--mj-transition-base);\n}\n\n.group-edit-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-default);\n color: var(--mj-text-secondary);\n}\n\n.group-edit-btn.danger:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n/* Pin Card */\n.pin-card {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n cursor: pointer;\n transition: all 0.25s ease;\n position: relative;\n}\n\n.pin-card:hover {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-border-default));\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.pin-card.edit-mode {\n cursor: grab;\n}\n\n.pin-card.edit-mode:active {\n cursor: grabbing;\n}\n\n.pin-card.dragging {\n opacity: 0.5;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-lg);\n transform: rotate(2deg);\n}\n\n.pin-card.drag-over {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n/* Edit controls overlay */\n.edit-controls {\n position: absolute;\n top: 8px;\n left: 8px;\n right: 8px;\n display: flex;\n justify-content: space-between;\n z-index: 10;\n pointer-events: none;\n}\n\n.edit-controls > * {\n pointer-events: auto;\n}\n\n.drag-handle {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n cursor: grab;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.drag-handle:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-actions {\n display: flex;\n gap: 4px;\n}\n\n.edit-card-btn {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.edit-card-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-btn.delete:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n}\n\n/* Pin Thumbnail */\n.pin-thumbnail {\n width: 100%;\n aspect-ratio: 16 / 10;\n overflow: hidden;\n position: relative;\n}\n\n.pin-thumbnail img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.pin-thumbnail.icon-mode {\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--pin-icon-color, var(--mj-text-muted)) 10%, var(--mj-bg-surface-card));\n}\n\n.pin-thumbnail.icon-mode > i {\n font-size: 36px;\n color: var(--pin-icon-color, var(--mj-text-muted));\n opacity: 0.7;\n}\n\n/* Action-pin card: colored gradient background with white icon/SVG */\n.pin-thumbnail.action-mode {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse, white);\n background: var(--mj-brand-primary);\n}\n\n.pin-thumbnail.action-mode > i {\n font-size: 36px;\n color: var(--mj-text-inverse, white);\n}\n\n/* Hover overlay */\n.pin-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n pointer-events: none;\n background: rgba(0,0,0,0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.pin-card:hover .pin-overlay {\n opacity: 1;\n pointer-events: auto;\n}\n\n.open-btn {\n padding: 8px 20px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n border: none;\n border-radius: var(--mj-radius-md);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n box-shadow: var(--mj-shadow-md);\n}\n\n/* Pin Info */\n.pin-info {\n padding: 10px 12px;\n}\n\n.pin-name {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-bottom: 4px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.pin-name .more-btn {\n margin-left: auto;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 4px;\n font-size: 14px;\n}\n\n/* Also reveal on keyboard focus \u2014 the pin's overflow menu is the only route to\n rename/remove/configure, and at opacity 0 it was pointer-only: invisible to a\n tabbing keyboard user and unreachable without a hover. */\n.pin-card:hover .pin-name .more-btn,\n.pin-card:focus-within .pin-name .more-btn {\n opacity: 1;\n}\n\n.pin-name .more-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.pin-name-input {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n padding: 2px 6px;\n width: 100%;\n outline: none;\n background: var(--mj-bg-surface);\n}\n\n.pin-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.pin-meta > i {\n font-size: 10px;\n}\n\n.pin-app-badge {\n background: var(--mj-bg-surface-card);\n padding: 1px 6px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n/* Add Pin Card */\n.add-pin-card {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-lg);\n border: 2px dashed var(--mj-border-default);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 180px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n gap: 8px;\n color: var(--mj-text-muted);\n}\n\n.add-pin-card:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-pin-card i {\n font-size: 28px;\n}\n\n.add-pin-card span {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n}\n\n/* ========================================\n PIN CONTEXT MENU (ELLIPSIS)\n ======================================== */\n.pin-context-menu {\n position: fixed;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10001;\n overflow: hidden;\n animation: pinMenuIn 0.15s ease;\n}\n\n@keyframes pinMenuIn {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.pin-context-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 9px 14px;\n cursor: pointer;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.pin-context-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.pin-context-item i {\n width: 16px;\n text-align: center;\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n}\n\n.pin-context-item.danger {\n color: var(--mj-status-error);\n}\n\n.pin-context-item.danger i {\n color: var(--mj-status-error);\n}\n\n.pin-context-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n.pin-context-item.submenu-header {\n font-weight: var(--mj-font-medium);\n cursor: default;\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n padding: 6px 14px;\n}\n\n.pin-context-item.submenu-header:hover {\n background: transparent;\n}\n\n.pin-context-item.submenu-item {\n padding-left: 30px;\n font-size: var(--mj-text-sm);\n}\n\n.pin-context-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* ========================================\n SLIDE-IN PANEL (Add Pin)\n ======================================== */\n.slide-panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 2000;\n}\n\n.slide-panel {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 400px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-xl);\n z-index: 2001;\n display: flex;\n flex-direction: column;\n animation: slideIn 0.3s ease;\n}\n\n@keyframes slideIn {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n.slide-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.slide-panel-header h3 {\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n}\n\n.slide-panel-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.slide-panel-close {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.slide-panel-close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Search box */\n.search-box {\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.search-input-wrapper {\n display: flex;\n align-items: center;\n gap: 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 8px 12px;\n transition: all var(--mj-transition-base);\n}\n\n.search-input-wrapper:focus-within {\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-input-wrapper i {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.search-input-wrapper input {\n border: none;\n outline: none;\n background: transparent;\n font-size: 14px;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.search-input-wrapper input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n/* Group selector */\n.group-selector {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.group-selector label {\n font-weight: var(--mj-font-medium);\n white-space: nowrap;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.group-selector select {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.new-group-input {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n/* Panel results */\n.panel-results {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n}\n\n.panel-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.panel-section {\n margin-bottom: 20px;\n}\n\n/* Section header (title row + chevron) now owned by <mj-accordion-panel>. */\n\n/* Section count pill migrated to <mj-accordion-badge mj-accordion-badge--right>;\n bespoke .panel-count rule removed. */\n\n/* App hierarchy in panel */\n.panel-app-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px 6px 12px;\n margin-top: 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.panel-app-header:first-child {\n margin-top: 0;\n}\n\n.panel-app-icon {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-app-icon i {\n font-size: 14px;\n color: var(--panel-app-color);\n}\n\n.panel-app-name {\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* Nav items under app \u2014 indented with left border accent */\n.panel-item.panel-nav-item {\n padding: 10px 12px 10px 32px;\n margin-left: 12px;\n border-left: 2px solid var(--mj-border-subtle);\n}\n\n.panel-item.panel-nav-item:last-of-type {\n border-left-color: transparent;\n}\n\n.panel-item.panel-nav-item:hover {\n border-left-color: var(--mj-brand-primary);\n}\n\n/* New group row */\n.new-group-row {\n padding: 0 20px 12px 20px;\n}\n\n.new-group-input {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n.panel-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: var(--mj-radius-md);\n transition: all var(--mj-transition-base);\n cursor: pointer;\n}\n\n.panel-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.panel-item-icon {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-item-icon i {\n font-size: 14px;\n}\n\n.panel-item-info {\n flex: 1;\n min-width: 0;\n}\n\n.panel-item-name {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.panel-item-sub {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.panel-item-action {\n flex-shrink: 0;\n}\n\n.panel-item-action button {\n padding: 4px 12px;\n border-radius: var(--mj-radius-sm);\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.pin-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.pin-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.pinned-badge {\n background: transparent;\n color: var(--mj-status-success);\n border: 1px solid var(--mj-status-success);\n cursor: default !important;\n}\n\n\n/* ========================================\n RESPONSIVE DESIGN\n ======================================== */\n\n/* Tablet and smaller desktop */\n@media (max-width: 1200px) {\n .quick-access-sidebar {\n width: 280px;\n }\n\n .home-dashboard.sidebar-open .main-content {\n margin-right: 280px;\n }\n\n .apps-grid {\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n }\n}\n\n/* Tablet */\n@media (max-width: 992px) {\n .main-content {\n padding: 24px;\n }\n\n .greeting-section h1 {\n font-size: var(--mj-text-3xl);\n }\n\n /* Make sidebar an overlay on tablet */\n .quick-access-sidebar {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n }\n\n .home-dashboard.sidebar-open .main-content {\n margin-right: 0;\n }\n\n /* Show backdrop when sidebar is open on tablet */\n .home-dashboard.sidebar-open::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 320px;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n /* Keep the fixed-height + scroll contract on mobile (matches desktop and the\n shared <mj-page-layout>/<mj-page-body> primitives). Overriding to\n height:auto / overflow:visible breaks .main-content's flex:1 scroll inside\n the fixed-height shell, leaving the page non-scrollable. */\n .main-content {\n padding: 20px;\n padding-bottom: 100px; /* Space for FAB button */\n }\n\n .home-header {\n flex-direction: column;\n gap: 16px;\n margin-bottom: 24px;\n }\n\n .greeting-section h1 {\n font-size: var(--mj-text-2xl);\n }\n\n /* Full-width sidebar on mobile \u2014 fixed overlay covering full viewport */\n .quick-access-sidebar {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 10000;\n border-left: none;\n border-top: none;\n }\n\n /* No separate backdrop needed on mobile \u2014 sidebar covers full screen */\n .home-dashboard.sidebar-open::before {\n display: none;\n }\n\n /* No ::after backdrop needed on mobile */\n .home-dashboard.sidebar-open::after {\n display: none;\n }\n\n .pin-grid {\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 12px;\n }\n\n .slide-panel {\n width: 100%;\n }\n\n .apps-grid {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n .app-card {\n padding: 16px;\n }\n\n .app-icon {\n width: 44px;\n height: 44px;\n }\n\n .app-icon i {\n font-size: var(--mj-text-lg);\n }\n\n .app-name {\n font-size: var(--mj-text-sm);\n }\n\n .nav-preview {\n display: none;\n }\n\n /* Move FAB to bottom-right on mobile \u2014 fixed so it stays visible while scrolling */\n .sidebar-fab-toggle {\n position: fixed;\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: var(--mj-text-lg);\n }\n}\n\n@media (max-width: 480px) {\n .main-content {\n padding: 16px;\n padding-bottom: 80px;\n }\n\n .greeting-section h1 {\n font-size: var(--mj-text-xl);\n }\n\n .greeting-section .date {\n font-size: var(--mj-text-sm);\n }\n\n .section-title {\n font-size: var(--mj-text-base);\n margin-bottom: 16px;\n }\n\n .sidebar-fab-toggle {\n bottom: 16px;\n right: 16px;\n width: 44px;\n height: 44px;\n font-size: var(--mj-text-base);\n }\n}\n"] }]
|
|
3678
|
+
args: [{ standalone: false, selector: 'mj-home-dashboard', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"home-dashboard\" [class.sidebar-open]=\"SidebarOpen && ShowQuickAccess\">\n <!-- Main Content Area -->\n <div class=\"main-content\">\n <!-- Overview: the greeting, Pinned and My applications in one centered column -->\n @if (ShowOverview) {\n <div class=\"home-overview\">\n <!-- Header Section -->\n <div class=\"home-header\">\n <div class=\"greeting-section\">\n <h1>{{ Greeting }}, {{ GreetingName }}</h1>\n <p class=\"date\">{{ FormattedDate }}</p>\n </div>\n </div>\n\n <!-- Pinned Section: collapses to its header (title, Add Pin / Dashboards / Edit, or Done) -->\n <mj-accordion-panel class=\"pinned-section\" [Bare]=\"true\" [TitleIconMuted]=\"true\" [HeadingLevel]=\"2\" [FlushBody]=\"true\"\n [Expanded]=\"PinnedExpanded\" (ExpandedChange)=\"OnPinnedExpandedChange($event)\">\n <ng-template mjAccordionTitle>\n <span class=\"pinned-title\"><i class=\"fa-solid fa-thumbtack\" aria-hidden=\"true\"></i> Pinned</span>\n </ng-template>\n <ng-template mjAccordionActions>\n <div class=\"pinned-actions\">\n @if (EditMode) {\n <button type=\"button\" mjButton Variant=\"success\" Size=\"sm\" (click)=\"ToggleEditMode()\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i> <span class=\"pin-action-label\">Done</span>\n </button>\n } @else {\n <button type=\"button\" mjButton Variant=\"primary\" Size=\"sm\" (click)=\"OpenAddPinPanel()\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i> <span class=\"pin-action-label\">Add Pin</span>\n </button>\n <mj-home-dashboard-switcher Look=\"button\" Align=\"right\" Label=\"Dashboards\"\n [Dashboards]=\"PinnedDashboards\" [CurrentId]=\"null\"\n (Pick)=\"OnSwitcherPick($event)\" (New)=\"OpenNewDashboardDialog()\" (ManagePins)=\"ManagePins()\">\n </mj-home-dashboard-switcher>\n @if (PinnedItems.length > 0) {\n <button type=\"button\" mjButton Variant=\"secondary\" Size=\"sm\" (click)=\"ToggleEditMode()\">\n <i class=\"fa-solid fa-pen\" aria-hidden=\"true\"></i> <span class=\"pin-action-label\">Edit</span>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-template mjAccordionBody>\n <div class=\"pinned-body\">\n @if (EditMode) {\n <div class=\"edit-mode-banner\">\n <i class=\"fa-solid fa-arrows-up-down-left-right\"></i>\n <span><strong>Edit mode</strong> \u2014 Drag cards to reorder. Click names to rename.</span>\n </div>\n }\n\n <!-- Empty State -->\n @if (PinnedItems.length === 0 && (EditMode || !HidePinEmptyState)) {\n <div class=\"pin-empty-state\">\n @if (!EditMode) {\n <button type=\"button\" class=\"pin-empty-close\" (click)=\"DismissPinEmptyState()\" title=\"Hide this\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n }\n <mj-empty-state Icon=\"fa-solid fa-thumbtack\"\n Title=\"No pinned items yet\"\n Message=\"Pin your favorite dashboards, views, queries, and reports for quick access.\">\n <button actions mjButton variant=\"primary\" (click)=\"OpenAddPinPanel()\">\n <i class=\"fa-solid fa-plus\"></i> Add your first pin\n </button>\n @if (!EditMode && !HidePinEmptyState) {\n <button actions mjButton variant=\"flat\" (click)=\"DismissPinEmptyState()\">\n Don't show this again\n </button>\n }\n </mj-empty-state>\n </div>\n }\n\n <!-- Pin Grid: the ungrouped pins, then each group under its header, from one card markup -->\n @if (PinnedItems.length > 0) {\n <div class=\"pin-grid\">\n @for (section of PinSections; track section.Key) {\n @if (section.Group !== null) {\n <div class=\"group-header\">\n @if (EditMode && EditingGroupName === section.Group) {\n <input class=\"group-name-input\" [value]=\"section.Group\"\n (blur)=\"SaveGroupName(section.Group, GetInputValue($event))\"\n (keydown.enter)=\"SaveGroupName(section.Group, GetInputValue($event))\" />\n } @else {\n <span class=\"group-name\" (click)=\"EditMode ? StartEditingGroup(section.Group) : null\">{{ section.Group }}</span>\n }\n <div class=\"group-line\"></div>\n <span class=\"group-count\">{{ section.Pins.length }} pins</span>\n @if (EditMode) {\n <div class=\"group-edit-controls\">\n <button type=\"button\" class=\"group-edit-btn danger\" (click)=\"RemoveGroup(section.Group)\">\n <i class=\"fa-solid fa-folder-minus\" aria-hidden=\"true\"></i> Remove Group\n </button>\n </div>\n }\n </div>\n }\n @for (pin of section.Pins; track pin.Id) {\n <div class=\"pin-card\"\n [class.edit-mode]=\"EditMode\"\n [class.dragging]=\"DraggingPinId === pin.Id\"\n [class.drag-over]=\"DragOverPinId === pin.Id\"\n [class.menu-open]=\"PinMenuPin?.Id === pin.Id\"\n [draggable]=\"EditMode\"\n (dragstart)=\"OnDragStart($event, pin)\" (dragover)=\"OnDragOver($event, pin)\" (dragleave)=\"OnDragLeave()\"\n (drop)=\"OnDrop($event, pin)\" (dragend)=\"OnDragEnd()\"\n (click)=\"OnPinClick(pin)\">\n\n <!-- Edit mode controls -->\n @if (EditMode) {\n <div class=\"edit-controls\">\n <div class=\"drag-handle\"><i class=\"fa-solid fa-grip-vertical\" aria-hidden=\"true\"></i></div>\n <div class=\"edit-card-actions\">\n <button type=\"button\" class=\"edit-card-btn delete\" aria-label=\"Remove pin\" title=\"Remove pin\"\n (click)=\"RemovePin(pin.Id); $event.stopPropagation()\"><i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i></button>\n </div>\n </div>\n }\n\n <!-- Thumbnail: the pin's image, the action accent, or the brand icon tile -->\n @if (pin.Thumbnail) {\n <div class=\"pin-thumbnail\">\n <img [src]=\"pin.Thumbnail\" [alt]=\"PinName(pin)\" />\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button type=\"button\" mjButton Variant=\"secondary\" Size=\"sm\" [attr.aria-label]=\"'Open ' + PinName(pin)\"\n (click)=\"OnPinClick(pin); $event.stopPropagation()\">Open</button>\n </div>\n }\n </div>\n } @else if (pin.ResourceType === 'Actions') {\n <div class=\"pin-thumbnail action-mode\"\n [style.background]=\"'linear-gradient(135deg, ' + GetPinAccentColor(pin) + ' 0%, ' + GetPinAccentColor(pin) + 'cc 100%)'\">\n <i [class]=\"GetPinIcon(pin)\" aria-hidden=\"true\"></i>\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button type=\"button\" mjButton Variant=\"secondary\" Size=\"sm\" [attr.aria-label]=\"'Run ' + PinName(pin)\"\n (click)=\"OnPinClick(pin); $event.stopPropagation()\">Run</button>\n </div>\n }\n </div>\n } @else {\n <div class=\"pin-thumbnail icon-mode\">\n <i [class]=\"GetPinIcon(pin)\" aria-hidden=\"true\"></i>\n @if (!EditMode) {\n <div class=\"pin-overlay\">\n <button type=\"button\" mjButton Variant=\"secondary\" Size=\"sm\" [attr.aria-label]=\"'Open ' + PinName(pin)\"\n (click)=\"OnPinClick(pin); $event.stopPropagation()\">Open</button>\n </div>\n }\n </div>\n }\n\n <!-- Pin Info: the name with the pin options button, and the kind line -->\n <div class=\"pin-info\">\n @if (EditMode && EditingPinId === pin.Id) {\n <input class=\"pin-name-input\" [value]=\"PinName(pin)\" [attr.aria-label]=\"'Name of ' + PinName(pin)\"\n (blur)=\"SavePinName(pin.Id, GetInputValue($event))\"\n (keydown.enter)=\"OnPinNameEnter(pin.Id, $event)\"\n (click)=\"$event.stopPropagation()\" />\n } @else {\n <div class=\"pin-name\" (click)=\"EditMode ? StartEditingPin(pin.Id, $event) : null\">\n <span class=\"pin-name-text\">{{ PinName(pin) }}</span>\n @if (!EditMode) {\n <button type=\"button\" class=\"more-btn\" [attr.aria-label]=\"'Pin options for ' + PinName(pin)\" title=\"Pin options\" aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"PinMenuPin?.Id === pin.Id\" (click)=\"ShowPinMenu($event, pin)\">\n <i class=\"fa-solid fa-ellipsis\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n <div class=\"pin-meta\">\n @if (pin.ResourceType === 'Dashboards') {\n <i class=\"fa-solid fa-gauge-high\" aria-hidden=\"true\"></i>\n }\n <span class=\"pin-kind\">{{ GetResourceTypeLabel(pin) }}</span>\n </div>\n </div>\n </div>\n }\n }\n\n <!-- Add Pin card (edit mode) -->\n @if (EditMode) {\n <div class=\"add-pin-card\" (click)=\"OpenAddPinPanel()\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span>Add Pin</span>\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n </mj-accordion-panel>\n\n <!-- My applications -->\n <section class=\"apps-section\">\n <h2 class=\"section-title\">My applications</h2>\n <div class=\"apps-grid\">\n @for (appData of AppsDisplayData; track TrackByApp($index, appData)) {\n <div class=\"app-card\" [mjClickable]=\"appData.app.Name\" [TestId]=\"'app-tile-' + appData.app.Name\"\n [style.--app-color]=\"appData.color\" (click)=\"OnAppClick(appData.app)\">\n <div class=\"app-icon\" aria-hidden=\"true\"><i [class]=\"appData.icon\"></i></div>\n <div class=\"app-info\">\n <h3 class=\"app-name\">{{ appData.app.Name }}</h3>\n @if (appData.app.Description) {\n <p class=\"app-description\">{{ appData.app.Description }}</p>\n }\n </div>\n </div>\n }\n </div>\n <!-- Empty State -->\n @if (Apps.length === 0) {\n <mj-empty-state Icon=\"fa-solid fa-folder-open\"\n Title=\"No Applications Available\"\n Message=\"You don't have any applications configured yet.\"\n ActionText=\"Configure Applications\"\n ActionIcon=\"fa-solid fa-gear\"\n (Action)=\"OpenConfigDialog()\" />\n }\n </section>\n </div>\n }\n\n <!-- Dashboard view: a pinned dashboard at full size in place of the overview, in the shared dashboard editor -->\n @if (ShowDashboardView && CurrentDashboardId) {\n <mj-dashboard-editor #dashboardEditor class=\"home-dashboard-view\"\n [Provider]=\"Provider\" [DashboardId]=\"CurrentDashboardId\"\n [(StartInEditMode)]=\"DashboardStartsInEditMode\"\n [TitleTemplate]=\"homeDashboardTitle\" [ShowOpenInDashboards]=\"true\" BodyStyle=\"card\"\n (Loaded)=\"OnDashboardViewLoaded($event)\"\n (EditingChange)=\"OnDashboardEditingChange($event)\" (NameChanged)=\"OnDashboardSaved()\" (Saved)=\"OnDashboardSaved()\"\n (LoadFailed)=\"OnDashboardViewLoadFailed()\"\n (OpenInDashboardsRequested)=\"OpenDashboardInDashboardsApp($event)\"\n (NavigationRequested)=\"OnDashboardNavigationRequested($event)\">\n </mj-dashboard-editor>\n }\n\n <!-- The dashboard view's title in view mode: the breadcrumb over the Dashboards switcher, whose trigger is the view's heading -->\n <ng-template #homeDashboardTitle let-dashboard>\n <div class=\"dashboard-title\">\n <nav class=\"dashboard-crumb\" aria-label=\"Breadcrumb\">\n <button type=\"button\" class=\"crumb-home\" (click)=\"OnSwitcherPick(null)\"><i class=\"fa-solid fa-house\" aria-hidden=\"true\"></i> Home</button>\n <span aria-hidden=\"true\">/</span>\n <span>Pinned dashboards</span>\n </nav>\n <mj-home-dashboard-switcher Look=\"title\" Align=\"left\" [HeadingLevel]=\"1\" [Label]=\"dashboard.Name\"\n [Dashboards]=\"PinnedDashboards\" [CurrentId]=\"dashboard.ID\"\n (Pick)=\"OnSwitcherPick($event)\" (New)=\"OpenNewDashboardDialog()\" (ManagePins)=\"ManagePins()\">\n </mj-home-dashboard-switcher>\n </div>\n </ng-template>\n\n <!-- Pin options menu (ellipsis): fixed next to its button (below it, or above it when there is no room below), outside the cards so it stacks above them -->\n @if (PinMenuVisible && PinMenuPin) {\n <div #pinMenu class=\"pin-context-menu\" role=\"menu\" [attr.aria-label]=\"'Options for ' + PinName(PinMenuPin)\"\n [style.left.px]=\"PinMenuX\" [style.top.px]=\"PinMenuY\" [style.max-height.px]=\"PinMenuMaxHeight\" (keydown)=\"OnPinMenuKeydown($event)\">\n <button type=\"button\" role=\"menuitem\" class=\"pin-context-item\" (click)=\"OnPinMenuEdit()\">\n <i class=\"fa-solid fa-pen\" aria-hidden=\"true\"></i><span>Edit</span>\n </button>\n <div class=\"pin-context-divider\" role=\"separator\"></div>\n <div role=\"group\" [attr.aria-labelledby]=\"PinMenuGroupLabelId\">\n <div class=\"pin-context-item submenu-header\" [id]=\"PinMenuGroupLabelId\"><i class=\"fa-solid fa-folder\" aria-hidden=\"true\"></i><span>Move to Group</span></div>\n @if (PinMenuPin.Group) {\n <button type=\"button\" role=\"menuitem\" class=\"pin-context-item submenu-item\" (click)=\"OnPinMenuMoveToGroup(undefined)\"><span>(No group)</span></button>\n }\n @for (group of PinGroups; track group) {\n @if (group !== PinMenuPin.Group) {\n <button type=\"button\" role=\"menuitem\" class=\"pin-context-item submenu-item\" (click)=\"OnPinMenuMoveToGroup(group)\"><span>{{ group }}</span></button>\n }\n }\n </div>\n <div class=\"pin-context-divider\" role=\"separator\"></div>\n <button type=\"button\" role=\"menuitem\" class=\"pin-context-item danger\" (click)=\"OnPinMenuUnpin()\">\n <i class=\"fa-solid fa-thumbtack-slash\" aria-hidden=\"true\"></i><span>Unpin</span>\n </button>\n </div>\n }\n\n <!-- Add Pin Slide-In Panel -->\n @if (AddPanelOpen) {\n <div class=\"slide-panel-backdrop\" (click)=\"CloseAddPinPanel()\"></div>\n <div class=\"slide-panel\">\n <div class=\"slide-panel-header\">\n <h3><i class=\"fa-solid fa-thumbtack\"></i> Add Pin</h3>\n <button class=\"slide-panel-close\" (click)=\"CloseAddPinPanel()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <div class=\"search-box\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <input type=\"text\"\n placeholder=\"Search apps, dashboards, views, queries...\"\n [(ngModel)]=\"AddPanelSearchQuery\" />\n </div>\n </div>\n\n <div class=\"group-selector\">\n <label><i class=\"fa-solid fa-folder\"></i> Add to group:</label>\n <select [(ngModel)]=\"AddPanelSelectedGroup\">\n <option value=\"\">(No group)</option>\n @for (group of PinGroups; track group) {\n <option [value]=\"group\">{{ group }}</option>\n }\n <option value=\"__new__\">+ New group...</option>\n </select>\n </div>\n @if (AddPanelSelectedGroup === '__new__') {\n <div class=\"new-group-row\">\n <input class=\"new-group-input\"\n type=\"text\"\n placeholder=\"Enter new group name...\"\n [(ngModel)]=\"AddPanelNewGroupName\" />\n </div>\n }\n\n <div class=\"panel-results\">\n @if (AddPanelLoading) {\n <div class=\"panel-loading\">\n <mj-loading text=\"Loading resources...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n <!-- Apps with Nav Items -->\n @if (FilterApps().length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['apps']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('apps', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-grid-2\"></i> Applications\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterApps().length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (app of FilterApps(); track app.appId) {\n <div class=\"panel-app-header\" [style.--panel-app-color]=\"app.color\">\n <div class=\"panel-app-icon\">\n <i [class]=\"app.icon\"></i>\n </div>\n <span class=\"panel-app-name\">{{ app.appName }}</span>\n </div>\n @for (ni of app.navItems; track ni.label) {\n <div class=\"panel-item panel-nav-item\">\n <div class=\"panel-item-icon\" [style.background]=\"'color-mix(in srgb, ' + app.color + ' 10%, var(--mj-bg-surface-card))'\">\n <i [class]=\"ni.icon\" [style.color]=\"app.color\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ ni.label }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (ni.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinAppNavItem(app.appName, app.icon, app.color, ni.label, ni.icon)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Dashboards (metadata-driven Config type only) -->\n @if (FilterPanelItems(AvailableDashboards).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['dashboards']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('dashboards', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-gauge-high\"></i> Dashboards\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableDashboards).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableDashboards); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-gauge-high\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (item.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinFromPanel('Dashboards', item.id, item.name)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Views -->\n @if (FilterPanelItems(AvailableViews).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['views']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('views', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-table-list\"></i> Views\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableViews).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableViews); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-table-list\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n <div class=\"panel-item-sub\">{{ item.entityName }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (item.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinFromPanel('User Views', item.id, item.name)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Queries -->\n @if (FilterPanelItems(AvailableQueries).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['queries']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('queries', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-database\"></i> Queries\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableQueries).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableQueries); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-database\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n </div>\n <div class=\"panel-item-action\">\n @if (item.pinned) {\n <button class=\"pinned-badge\"><i class=\"fa-solid fa-check\"></i> Pinned</button>\n } @else {\n <button class=\"pin-btn\" (click)=\"PinFromPanel('Queries', item.id, item.name)\">\n <i class=\"fa-solid fa-plus\"></i> Pin\n </button>\n }\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n\n <!-- Quick Actions -->\n @if (FilterPanelItems(AvailableActions).length > 0) {\n <mj-accordion-panel class=\"panel-section\" Size=\"sm\" [FlushBody]=\"true\"\n [Expanded]=\"!PanelSectionCollapsed['actions']\"\n (ExpandedChange)=\"OnPanelSectionExpandedChange('actions', $event)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-bolt\"></i> Quick Actions\n <span class=\"mj-accordion-badge mj-accordion-badge--right\">{{ FilterPanelItems(AvailableActions).length }}</span>\n </ng-template>\n <ng-template mjAccordionBody>\n @for (item of FilterPanelItems(AvailableActions); track item.id) {\n <div class=\"panel-item\">\n <div class=\"panel-item-icon\" style=\"background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface-card))\">\n <i class=\"fa-solid fa-bolt\" style=\"color: var(--mj-brand-primary)\"></i>\n </div>\n <div class=\"panel-item-info\">\n <div class=\"panel-item-name\">{{ item.name }}</div>\n @if (item.description) {\n <div class=\"panel-item-sub\">{{ item.description }}</div>\n }\n </div>\n <div class=\"panel-item-action\">\n <button class=\"pin-btn\" (click)=\"OpenActionPinConfig(item.id, item.name, item.description)\">\n <i class=\"fa-solid fa-sliders\"></i> Configure\n </button>\n </div>\n </div>\n }\n </ng-template>\n </mj-accordion-panel>\n }\n }\n </div>\n </div>\n }\n\n <!-- Action Pin Dialogs -->\n <mj-action-pin-config-dialog\n [Visible]=\"ActionConfigDialogVisible\"\n [ActionID]=\"ActionConfigActionId\"\n [ActionName]=\"ActionConfigActionName\"\n [ActionDescription]=\"ActionConfigActionDescription\"\n (Result)=\"OnActionConfigResult($event)\">\n </mj-action-pin-config-dialog>\n\n <mj-action-pin-runner-dialog\n [Visible]=\"ActionRunnerDialogVisible\"\n [Pin]=\"ActionRunnerPin\"\n (Result)=\"OnActionRunnerResult($event)\">\n </mj-action-pin-runner-dialog>\n\n <!-- New dashboard: asks for the name; Cancel creates nothing -->\n <mj-dashboard-name-dialog [Visible]=\"ShowNewDashboardDialog\" [MaxLength]=\"NewDashboardNameMaxLength\"\n [Processing]=\"IsCreatingDashboard\" (Confirmed)=\"OnNewDashboardNamed($event)\" (Cancelled)=\"OnNewDashboardCancelled()\">\n </mj-dashboard-name-dialog>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading your applications...\" size=\"large\"></mj-loading>\n </div>\n }\n </div>\n\n <!-- Collapsible Right Sidebar (the overview only) -->\n @if (ShowQuickAccess) {\n <div class=\"quick-access-sidebar\">\n <div class=\"sidebar-header\">\n <h3>\n <i class=\"fa-solid fa-bolt\"></i>\n Quick Access\n </h3>\n <button class=\"sidebar-close-btn\" (click)=\"toggleSidebar()\" title=\"Close panel\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div class=\"sidebar-content\">\n <!-- Unread Notifications Section -->\n @if (unreadNotifications.length > 0) {\n <div class=\"sidebar-section notifications-section\">\n <h4 class=\"sidebar-section-title\">\n <i class=\"fa-solid fa-bell\"></i>\n Notifications\n <span class=\"section-badge\">{{ unreadNotifications.length }}</span>\n </h4>\n <div class=\"sidebar-items\">\n @for (notification of unreadNotifications; track trackByNotification($index, notification)) {\n <div\n class=\"sidebar-item notification-item\"\n [mjClickable]=\"notification.Title\"\n testId=\"notification-item\"\n (click)=\"onNotificationClick(notification)\">\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ notification.Title }}</span>\n <span class=\"sidebar-item-subtitle\">{{ notification.Message | slice:0:40 }}{{ (notification.Message?.length || 0) > 40 ? '...' : '' }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Favorites Section -->\n @if (favorites.length > 0 || favoritesLoading) {\n <div class=\"sidebar-section favorites-section\">\n <h4 class=\"sidebar-section-title\">\n <i class=\"fa-solid fa-star\"></i>\n Favorites\n </h4>\n @if (!favoritesLoading) {\n <div class=\"sidebar-items\">\n @for (favorite of favorites; track trackByFavorite($index, favorite)) {\n <div\n class=\"sidebar-item favorite-item\"\n [mjClickable]=\"getFavoriteDisplayName(favorite)\"\n testId=\"favorite-item\"\n (click)=\"onFavoriteClick(favorite)\">\n <div class=\"sidebar-item-icon\">\n <i [class]=\"getEntityIconByName(favorite.Entity)\"></i>\n </div>\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ getFavoriteDisplayName(favorite) }}</span>\n <span class=\"sidebar-item-subtitle\">{{ favorite.Entity }}</span>\n </div>\n </div>\n }\n </div>\n }\n @if (favoritesLoading) {\n <div class=\"sidebar-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading...</span>\n </div>\n }\n </div>\n }\n <!-- Recents Section -->\n @if (recentItems.length > 0 || recentsLoading) {\n <div class=\"sidebar-section recents-section\">\n <h4 class=\"sidebar-section-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n Recent\n </h4>\n @if (!recentsLoading) {\n <div class=\"sidebar-items\">\n @for (item of recentItems; track trackByRecent($index, item)) {\n <div\n class=\"sidebar-item recent-item\"\n [mjClickable]=\"item.recordName || item.recordId\"\n testId=\"recent-item\"\n (click)=\"onRecentClick(item)\">\n <div class=\"sidebar-item-icon\">\n <i [class]=\"getEntityIconByName(item.entityName)\"></i>\n </div>\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ item.recordName || item.recordId }}</span>\n <span class=\"sidebar-item-subtitle\">{{ item.entityName }} \u00B7 {{ formatDate(item.latestAt) }}</span>\n </div>\n </div>\n }\n </div>\n }\n @if (recentsLoading) {\n <div class=\"sidebar-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading...</span>\n </div>\n }\n </div>\n }\n <!-- Empty sidebar state -->\n @if (!favoritesLoading && !recentsLoading && unreadNotifications.length === 0 && favorites.length === 0 && recentItems.length === 0) {\n <mj-empty-state class=\"sidebar-empty\" Size=\"compact\"\n Icon=\"fa-solid fa-inbox\"\n Title=\"No quick access items\" />\n }\n </div>\n </div>\n }\n\n <!-- Quick Access FAB Toggle (Fixed Button; the overview only) -->\n @if (ShowQuickAccess && !SidebarOpen) {\n <button class=\"sidebar-fab-toggle\"\n (click)=\"toggleSidebar()\"\n title=\"Quick Access\">\n <i class=\"fa-solid fa-bolt\"></i>\n @if (unreadNotifications.length > 0) {\n <span class=\"fab-badge\">{{ unreadNotifications.length }}</span>\n }\n </button>\n }\n\n <!-- App Configuration Dialog -->\n <mj-user-app-config\n #appConfigDialog\n [(ShowDialog)]=\"showConfigDialog\"\n (ConfigSaved)=\"onConfigSaved()\">\n </mj-user-app-config>\n</div>\n", styles: [".home-dashboard {\n display: flex;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n position: relative;\n}\n\n/* Main Content Area */\n.main-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow-y: auto;\n transition: margin-right var(--mj-transition-slow);\n}\n\n/* Sidebar open state adjusts main content on desktop */\n.home-dashboard.sidebar-open .main-content {\n margin-right: 320px;\n}\n\n/* The overview column: greeting, Pinned and My applications */\n.home-overview {\n width: 100%;\n max-width: 1180px;\n margin: 0 auto;\n padding: var(--mj-space-7) var(--mj-space-8) var(--mj-space-10);\n}\n\n/* Header: greeting */\n.home-header {\n display: flex;\n align-items: flex-end;\n gap: var(--mj-space-4);\n margin-bottom: var(--mj-space-6);\n}\n\n.greeting-section h1 {\n margin: 0;\n font-size: var(--mj-text-2xl);\n font-weight: var(--mj-font-bold);\n letter-spacing: var(--mj-tracking-tight);\n line-height: var(--mj-leading-tight);\n color: var(--mj-text-primary);\n}\n\n.greeting-section .date {\n margin: var(--mj-space-1) 0 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-muted);\n}\n\n/* ========================================\n DASHBOARD VIEW\n ======================================== */\n\n/* The dashboard view fills the page; the editor lays out its header and body. */\n.home-dashboard-view {\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 520px;\n}\n\n/* View-mode title: breadcrumb over the title switcher */\n.dashboard-title {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.dashboard-crumb {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.crumb-home {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 0;\n border: 0;\n background: transparent;\n font: inherit;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-link);\n cursor: pointer;\n}\n\n.crumb-home:hover {\n color: var(--mj-text-link-hover);\n}\n\n.crumb-home:focus-visible {\n outline: none;\n border-radius: var(--mj-radius-sm);\n box-shadow: var(--mj-focus-ring);\n}\n\n/* FAB Toggle Button for Quick Access - top-right on desktop */\n.sidebar-fab-toggle {\n position: absolute;\n top: 20px;\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: var(--mj-radius-full);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xl);\n cursor: pointer;\n box-shadow: var(--mj-shadow-brand-md);\n transition: all var(--mj-transition-base);\n z-index: 100;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sidebar-fab-toggle:hover {\n background: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n box-shadow: 0 6px 16px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n border-radius: var(--mj-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Loading State */\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n gap: 16px;\n color: var(--mj-text-muted);\n}\n\n.loading-spinner {\n font-size: var(--mj-text-4xl);\n color: var(--mj-brand-primary);\n}\n\n/* My applications */\n.apps-section {\n margin-bottom: var(--mj-space-8);\n}\n\n.section-title {\n margin: 0 0 var(--mj-space-3);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-bold);\n color: var(--mj-text-primary);\n}\n\n.apps-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));\n gap: var(--mj-space-3);\n}\n\n/* App Card: an icon tile in the app's color, then the name and description */\n.app-card {\n --app-color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: var(--mj-space-3);\n padding: var(--mj-space-4);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n cursor: pointer;\n transition:\n border-color var(--mj-transition-fast),\n box-shadow var(--mj-transition-fast),\n transform var(--mj-transition-fast);\n}\n\n.app-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.app-card:focus-visible {\n outline: none;\n box-shadow: var(--mj-focus-ring);\n}\n\n.app-icon {\n flex: 0 0 36px;\n display: grid;\n place-items: center;\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--app-color) 12%, transparent);\n color: var(--app-color);\n font-size: 16px;\n}\n\n.app-info {\n flex: 1;\n min-width: 0;\n}\n\n.app-name {\n margin: 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.app-description {\n margin: 2px 0 0;\n font-size: var(--mj-text-xs);\n line-height: var(--mj-leading-snug);\n color: var(--mj-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* ========================================\n RIGHT SIDEBAR\n ======================================== */\n.quick-access-sidebar {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform var(--mj-transition-slow);\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.home-dashboard.sidebar-open .quick-access-sidebar {\n transform: translateX(0);\n}\n\n.sidebar-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.sidebar-header h3 {\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sidebar-header h3 i {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n.sidebar-close-btn {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.sidebar-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n/* Sidebar Sections */\n.sidebar-section {\n margin-bottom: 20px;\n}\n\n.sidebar-section:last-child {\n margin-bottom: 0;\n}\n\n.sidebar-section-title {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 12px 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title i {\n font-size: var(--mj-text-xs);\n}\n\n.notifications-section .sidebar-section-title i {\n color: var(--mj-color-warning-600);\n}\n\n.favorites-section .sidebar-section-title i {\n color: var(--mj-status-warning);\n}\n\n.recents-section .sidebar-section-title i {\n color: var(--mj-brand-primary);\n}\n\n.section-badge {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: var(--mj-font-semibold);\n padding: 2px 6px;\n border-radius: var(--mj-radius-md);\n margin-left: auto;\n}\n\n/* Sidebar Items */\n.sidebar-items {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sidebar-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.sidebar-item:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.sidebar-item-icon {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.sidebar-item-icon i {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n}\n\n.notification-item .sidebar-item-icon {\n background: var(--mj-color-warning-50);\n}\n\n.notification-item .sidebar-item-icon i {\n color: var(--mj-color-warning-600);\n}\n\n.favorite-item .sidebar-item-icon {\n background: var(--mj-color-warning-50);\n}\n\n.favorite-item .sidebar-item-icon i {\n color: var(--mj-color-warning-500);\n}\n\n.recent-item .sidebar-item-icon {\n background: var(--mj-color-info-50);\n}\n\n.recent-item .sidebar-item-icon i {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-item-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n flex: 1;\n}\n\n.sidebar-item-title {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n padding: 8px 0;\n}\n\n.sidebar-loading i {\n color: var(--mj-brand-primary);\n}\n\n.sidebar-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n color: var(--mj-text-disabled);\n}\n\n.sidebar-empty i {\n font-size: var(--mj-text-4xl);\n margin-bottom: 12px;\n}\n\n.sidebar-empty p {\n margin: 0;\n font-size: var(--mj-text-sm);\n}\n\n\n/* ========================================\n PINNED SECTION\n ======================================== */\n/* The section's accordion panel. The panel's header row holds the title, the actions and the chevron. */\n.pinned-section {\n display: block;\n margin-bottom: var(--mj-space-8);\n}\n\n/* Section title in the panel's toggle. It takes the toggle's text color, so the hover cue shows. */\n.pinned-title {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-bold);\n}\n\n.pinned-actions {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n}\n\n/* The accordion body is flush (FlushBody); the grid gets its top gap here */\n.pinned-body {\n padding-top: var(--mj-space-3);\n}\n\n/* Edit Mode Banner */\n.edit-mode-banner {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n border-radius: var(--mj-radius-lg);\n padding: 12px 20px;\n margin-bottom: 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.edit-mode-banner i {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-base);\n}\n\n.edit-mode-banner strong {\n color: var(--mj-brand-primary);\n}\n\n/* Pin Empty State */\n.pin-empty-state {\n position: relative;\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n border: 2px dashed var(--mj-border-default);\n}\n\n.pin-empty-close {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: var(--mj-text-sm);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.pin-empty-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n/* Pin Grid */\n.pin-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: var(--mj-space-4);\n margin-bottom: var(--mj-space-3);\n}\n\n/* Group Header */\n.group-header {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0 4px 0;\n margin-top: 8px;\n}\n\n.group-name {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.group-line {\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.group-count {\n font-size: 11px;\n color: var(--mj-text-disabled);\n background: var(--mj-bg-surface-card);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.group-name-input {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n padding: 2px 8px;\n background: var(--mj-bg-surface);\n outline: none;\n width: 160px;\n}\n\n.group-edit-controls {\n display: flex;\n gap: 6px;\n}\n\n.group-edit-btn {\n background: none;\n border: 1px solid transparent;\n color: var(--mj-text-muted);\n font-size: 11px;\n cursor: pointer;\n padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all var(--mj-transition-base);\n}\n\n.group-edit-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-default);\n color: var(--mj-text-secondary);\n}\n\n.group-edit-btn.danger:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n}\n\n/* Pin Card */\n.pin-card {\n position: relative;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n cursor: pointer;\n transition:\n border-color var(--mj-transition-fast),\n box-shadow var(--mj-transition-fast),\n transform var(--mj-transition-fast);\n}\n\n.pin-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-md);\n transform: translateY(-2px);\n}\n\n.pin-card.edit-mode {\n cursor: grab;\n}\n\n.pin-card.edit-mode:active {\n cursor: grabbing;\n}\n\n.pin-card.dragging {\n opacity: 0.5;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-lg);\n transform: rotate(2deg);\n}\n\n.pin-card.drag-over {\n border-color: var(--mj-brand-primary);\n border-style: dashed;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n/* Edit controls overlay */\n.edit-controls {\n position: absolute;\n top: 8px;\n left: 8px;\n right: 8px;\n display: flex;\n justify-content: space-between;\n z-index: 10;\n pointer-events: none;\n}\n\n.edit-controls > * {\n pointer-events: auto;\n}\n\n.drag-handle {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n cursor: grab;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.drag-handle:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-actions {\n display: flex;\n gap: 4px;\n}\n\n.edit-card-btn {\n width: 28px;\n height: 28px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n border-radius: var(--mj-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-subtle);\n transition: all var(--mj-transition-base);\n}\n\n.edit-card-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-md);\n}\n\n.edit-card-btn.delete:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 8%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n}\n\n/* Pin Thumbnail */\n.pin-thumbnail {\n position: relative;\n width: 100%;\n aspect-ratio: 16 / 10;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.pin-thumbnail img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n/* Every pin but an action pin shows its icon on a brand-tinted tile */\n.pin-thumbnail.icon-mode {\n display: grid;\n place-items: center;\n}\n\n.pin-thumbnail.icon-mode > i {\n display: grid;\n place-items: center;\n width: 52px;\n height: 52px;\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 22px;\n}\n\n/* Action pins keep their accent gradient (inline style) and white icon */\n.pin-thumbnail.action-mode {\n display: grid;\n place-items: center;\n background: var(--mj-brand-primary);\n}\n\n.pin-thumbnail.action-mode > i {\n font-size: 36px;\n color: var(--mj-text-inverse, white);\n}\n\n/* Hover overlay with the Open (or Run) button */\n.pin-overlay {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n background: var(--mj-bg-overlay);\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--mj-transition-fast);\n}\n\n.pin-card:hover .pin-overlay,\n.pin-card:focus-within .pin-overlay {\n opacity: 1;\n pointer-events: auto;\n}\n\n/* Pin Info */\n.pin-info {\n padding: var(--mj-space-3);\n}\n\n.pin-name {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1);\n min-width: 0;\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.pin-name-text {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.pin-name .more-btn {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: 24px;\n height: 24px;\n margin: -4px -4px -4px 0;\n padding: 0;\n border: none;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 14px;\n cursor: pointer;\n opacity: 0;\n transition:\n opacity var(--mj-transition-fast),\n background-color var(--mj-transition-fast),\n color var(--mj-transition-fast);\n}\n\n/* Shown on hover, on keyboard focus, and while its menu is open */\n.pin-card:hover .more-btn,\n.pin-card:focus-within .more-btn,\n.pin-card.menu-open .more-btn {\n opacity: 1;\n}\n\n.pin-name .more-btn:hover,\n.pin-card.menu-open .more-btn {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.pin-name .more-btn:focus-visible {\n outline: none;\n box-shadow: var(--mj-focus-ring);\n}\n\n.pin-name-input {\n width: 100%;\n padding: 2px 6px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n outline: none;\n background: var(--mj-bg-surface);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n/* Kind line */\n.pin-meta {\n display: flex;\n align-items: center;\n gap: 5px;\n min-width: 0;\n margin-top: 2px;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.pin-meta > i {\n font-size: 11px;\n}\n\n.pin-kind {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pin-card,\n .app-card {\n transition: none;\n }\n .pin-card:hover,\n .app-card:hover {\n transform: none;\n }\n}\n\n/* Add Pin Card */\n.add-pin-card {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-lg);\n border: 2px dashed var(--mj-border-default);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 180px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n gap: 8px;\n color: var(--mj-text-muted);\n}\n\n.add-pin-card:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.add-pin-card i {\n font-size: 28px;\n}\n\n.add-pin-card span {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-semibold);\n}\n\n/* ========================================\n PIN CONTEXT MENU (ELLIPSIS)\n ======================================== */\n/* Fixed next to its button and above the page chrome; the component limits its height to the room on that side */\n.pin-context-menu {\n position: fixed;\n z-index: 10001;\n width: 220px;\n overflow-y: auto;\n padding: 6px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n animation: pinMenuIn var(--mj-transition-fast);\n}\n\n@keyframes pinMenuIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-context-item {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3);\n width: 100%;\n padding: 8px 10px;\n border: 0;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n font: inherit;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n text-align: left;\n cursor: pointer;\n}\n\n.pin-context-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Keyboard focus: a ring drawn inside the row */\n.pin-context-item:focus-visible {\n outline: none;\n background: var(--mj-bg-surface-hover);\n box-shadow: inset 0 0 0 var(--mj-ring-width) var(--mj-focus-ring-color);\n}\n\n.pin-context-item i {\n width: 14px;\n text-align: center;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.pin-context-item.danger,\n.pin-context-item.danger i {\n color: var(--mj-status-error);\n}\n\n.pin-context-item.submenu-header {\n padding-bottom: 4px;\n cursor: default;\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n}\n\n.pin-context-item.submenu-header:hover {\n background: transparent;\n}\n\n.pin-context-item.submenu-item {\n padding-left: 34px;\n}\n\n.pin-context-divider {\n height: 1px;\n margin: 6px 4px;\n background: var(--mj-border-default);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .pin-context-menu { animation: none; }\n}\n\n/* ========================================\n SLIDE-IN PANEL (Add Pin)\n ======================================== */\n.slide-panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 2000;\n}\n\n.slide-panel {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 400px;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-xl);\n z-index: 2001;\n display: flex;\n flex-direction: column;\n animation: slideIn 0.3s ease;\n}\n\n@keyframes slideIn {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n.slide-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.slide-panel-header h3 {\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n}\n\n.slide-panel-header h3 i {\n color: var(--mj-brand-primary);\n}\n\n.slide-panel-close {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: var(--mj-radius-md);\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all var(--mj-transition-base);\n}\n\n.slide-panel-close:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Search box */\n.search-box {\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.search-input-wrapper {\n display: flex;\n align-items: center;\n gap: 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 8px 12px;\n transition: all var(--mj-transition-base);\n}\n\n.search-input-wrapper:focus-within {\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-input-wrapper i {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.search-input-wrapper input {\n border: none;\n outline: none;\n background: transparent;\n font-size: 14px;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.search-input-wrapper input::placeholder {\n color: var(--mj-text-disabled);\n}\n\n/* Group selector */\n.group-selector {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n}\n\n.group-selector label {\n font-weight: var(--mj-font-medium);\n white-space: nowrap;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.group-selector select {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n cursor: pointer;\n}\n\n.new-group-input {\n flex: 1;\n padding: 4px 8px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n/* Panel results */\n.panel-results {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n}\n\n.panel-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n}\n\n.panel-section {\n margin-bottom: 20px;\n}\n\n/* Section header (title row + chevron) now owned by <mj-accordion-panel>. */\n\n/* Section count pill migrated to <mj-accordion-badge mj-accordion-badge--right>;\n bespoke .panel-count rule removed. */\n\n/* App hierarchy in panel */\n.panel-app-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px 6px 12px;\n margin-top: 8px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.panel-app-header:first-child {\n margin-top: 0;\n}\n\n.panel-app-icon {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-app-icon i {\n font-size: 14px;\n color: var(--panel-app-color);\n}\n\n.panel-app-name {\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* Nav items under app \u2014 indented with left border accent */\n.panel-item.panel-nav-item {\n padding: 10px 12px 10px 32px;\n margin-left: 12px;\n border-left: 2px solid var(--mj-border-subtle);\n}\n\n.panel-item.panel-nav-item:last-of-type {\n border-left-color: transparent;\n}\n\n.panel-item.panel-nav-item:hover {\n border-left-color: var(--mj-brand-primary);\n}\n\n/* New group row */\n.new-group-row {\n padding: 0 20px 12px 20px;\n}\n\n.new-group-input {\n width: 100%;\n padding: 6px 10px;\n border: 1px solid var(--mj-border-focus);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n outline: none;\n}\n\n.panel-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border-radius: var(--mj-radius-md);\n transition: all var(--mj-transition-base);\n cursor: pointer;\n}\n\n.panel-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.panel-item-icon {\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.panel-item-icon i {\n font-size: 14px;\n}\n\n.panel-item-info {\n flex: 1;\n min-width: 0;\n}\n\n.panel-item-name {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.panel-item-sub {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.panel-item-action {\n flex-shrink: 0;\n}\n\n.panel-item-action button {\n padding: 4px 12px;\n border-radius: var(--mj-radius-sm);\n font-size: 12px;\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.pin-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.pin-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.pinned-badge {\n background: transparent;\n color: var(--mj-status-success);\n border: 1px solid var(--mj-status-success);\n cursor: default !important;\n}\n\n\n/* ========================================\n RESPONSIVE DESIGN\n ======================================== */\n\n/* Tablet and smaller desktop */\n@media (max-width: 1200px) {\n .quick-access-sidebar {\n width: 280px;\n }\n\n .home-dashboard.sidebar-open .main-content {\n margin-right: 280px;\n }\n}\n\n/* Tablet */\n@media (max-width: 992px) {\n /* Make sidebar an overlay on tablet */\n .quick-access-sidebar {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px color-mix(in srgb, var(--mj-text-primary) 15%, transparent);\n }\n\n .home-dashboard.sidebar-open .main-content {\n margin-right: 0;\n }\n\n /* Show backdrop when sidebar is open on tablet */\n .home-dashboard.sidebar-open::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 320px;\n bottom: 0;\n background: var(--mj-bg-overlay);\n z-index: 999;\n }\n}\n\n/* Narrow screens: less page padding. The pin and app grids reflow on their own. */\n@media (max-width: 900px) {\n .home-overview {\n padding: var(--mj-space-5) var(--mj-space-4);\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .home-overview {\n padding-bottom: 100px; /* Space for FAB button */\n }\n\n /* Full-width sidebar on mobile \u2014 fixed overlay covering full viewport */\n .quick-access-sidebar {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 10000;\n border-left: none;\n border-top: none;\n }\n\n /* No separate backdrop needed on mobile \u2014 sidebar covers full screen */\n .home-dashboard.sidebar-open::before {\n display: none;\n }\n\n /* No ::after backdrop needed on mobile */\n .home-dashboard.sidebar-open::after {\n display: none;\n }\n\n .pin-grid {\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: var(--mj-space-3);\n }\n\n .slide-panel {\n width: 100%;\n }\n\n /* Move FAB to bottom-right on mobile \u2014 fixed so it stays visible while scrolling */\n .sidebar-fab-toggle {\n position: fixed;\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: var(--mj-text-lg);\n }\n}\n\n@media (max-width: 480px) {\n .home-overview {\n padding-bottom: 80px;\n }\n\n .greeting-section h1 {\n font-size: var(--mj-text-xl);\n }\n\n .greeting-section .date {\n font-size: var(--mj-text-sm);\n }\n\n /* Pinned header: the title without its icon, and icon-only actions, so it fits on one row.\n The action labels stay in the accessibility tree, so each button keeps its name. */\n .pinned-title i {\n display: none;\n }\n\n .pinned-actions .pin-action-label {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n\n .sidebar-fab-toggle {\n bottom: 16px;\n right: 16px;\n width: 44px;\n height: 44px;\n font-size: var(--mj-text-base);\n }\n}\n"] }]
|
|
3004
3679
|
}], () => [{ type: i1.ApplicationManager }, { type: i2.RecentAccessService }, { type: i0.ChangeDetectorRef }], { AppConfigDialog: [{
|
|
3005
3680
|
type: ViewChild,
|
|
3006
3681
|
args: ['appConfigDialog']
|
|
3682
|
+
}], pinMenuEl: [{
|
|
3683
|
+
type: ViewChild,
|
|
3684
|
+
args: ['pinMenu']
|
|
3685
|
+
}], dashboardEditor: [{
|
|
3686
|
+
type: ViewChild,
|
|
3687
|
+
args: ['dashboardEditor']
|
|
3007
3688
|
}] }); })();
|
|
3008
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(HomeDashboardComponent, { className: "HomeDashboardComponent", filePath: "src/Home/home-dashboard.component.ts", lineNumber:
|
|
3689
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(HomeDashboardComponent, { className: "HomeDashboardComponent", filePath: "src/Home/home-dashboard.component.ts", lineNumber: 98 }); })();
|
|
3690
|
+
function errorMessage(error) {
|
|
3691
|
+
return error instanceof Error ? error.message : String(error);
|
|
3692
|
+
}
|
|
3693
|
+
/** What a Home agent tool for a part of the overview says while a dashboard shows: the part shows on the overview only. */
|
|
3694
|
+
function overviewOnlyError(part) {
|
|
3695
|
+
return `${part} shows on the ${HOME_OVERVIEW_NAME} overview only. Use SwitchHomeDashboard with "${HOME_OVERVIEW_NAME}" first.`;
|
|
3696
|
+
}
|
|
3009
3697
|
//# sourceMappingURL=home-dashboard.component.js.map
|