@memberjunction/ng-dashboards 5.3.1 → 5.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -1
- package/dist/AI/components/charts/time-series-chart.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-filter-panel.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
- package/dist/AI/components/system/system-config-filter-panel.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
- package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -1
- package/dist/AI/index.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +2 -2
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-list.component.js +2 -2
- package/dist/APIKeys/api-key-list.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +2 -2
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/APIKeys/api-usage-panel.component.js +2 -2
- package/dist/APIKeys/api-usage-panel.component.js.map +1 -1
- package/dist/APIKeys/index.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/code-management.component.js.map +1 -1
- package/dist/Actions/components/entity-integration.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/executions-list-view.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-breadcrumb.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-list-item.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-toolbar.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-tree-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/index.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
- package/dist/Actions/components/security-permissions.component.js.map +1 -1
- package/dist/Actions/index.js.map +1 -1
- package/dist/Actions/services/action-explorer-state.service.js.map +1 -1
- package/dist/Communication/communication-dashboard.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/browser/component-browser.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.js.map +1 -1
- package/dist/ComponentStudio/components/workspace/editor-tabs.component.js.map +1 -1
- package/dist/ComponentStudio/index.js.map +1 -1
- package/dist/ComponentStudio/services/component-studio-state.service.js.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/Credentials/credentials-dashboard.component.js.map +1 -1
- package/dist/Credentials/index.js.map +1 -1
- package/dist/Credentials/pipes/group-by.pipe.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +25 -3
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +158 -34
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +57 -23
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +600 -445
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/DataExplorer/index.js.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +25 -0
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.js +6 -1
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts +21 -3
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +70 -36
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-application.js.map +1 -1
- package/dist/Home/home-dashboard.component.d.ts +20 -5
- package/dist/Home/home-dashboard.component.d.ts.map +1 -1
- package/dist/Home/home-dashboard.component.js +128 -79
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
- package/dist/Lists/index.js.map +1 -1
- package/dist/Lists/services/list-set-operations.service.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/index.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/MCP/mcp-filter-panel.component.js.map +1 -1
- package/dist/MCP/mcp-resource.component.js.map +1 -1
- package/dist/MCP/mcp.module.js.map +1 -1
- package/dist/MCP/services/mcp-tools.service.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/index.js.map +1 -1
- package/dist/Scheduling/components/job-slideout.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/SystemDiagnostics/index.js.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.js +3 -3
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/index.js.map +1 -1
- package/dist/Testing/components/testing-analytics-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-analytics.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/components/widgets/oracle-breakdown-table.component.js.map +1 -1
- package/dist/Testing/components/widgets/suite-tree.component.js.map +1 -1
- package/dist/Testing/components/widgets/test-run-detail-panel.component.js.map +1 -1
- package/dist/Testing/services/testing-instrumentation.service.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/index.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/VersionHistory/index.js.map +1 -1
- package/dist/__tests__/dashboards.test.js.map +1 -1
- package/dist/module.js.map +1 -1
- package/dist/public-api.js.map +1 -1
- package/dist/shared/pipes/highlight-search.pipe.js.map +1 -1
- package/dist/shared/pipes/index.js.map +1 -1
- package/dist/shared/shared-pipes.module.js.map +1 -1
- package/package.json +38 -38
|
@@ -134,22 +134,19 @@ function HomeDashboardComponent_Conditional_10_Conditional_8_For_8_Template(rf,
|
|
|
134
134
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
135
135
|
i0.ɵɵelementStart(0, "div", 46);
|
|
136
136
|
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_10_Conditional_8_For_8_Template_div_click_0_listener() { const notification_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r3 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r3.onNotificationClick(notification_r9)); });
|
|
137
|
-
i0.ɵɵelementStart(1, "div", 47);
|
|
138
|
-
i0.ɵɵ
|
|
137
|
+
i0.ɵɵelementStart(1, "div", 47)(2, "span", 48);
|
|
138
|
+
i0.ɵɵtext(3);
|
|
139
139
|
i0.ɵɵelementEnd();
|
|
140
|
-
i0.ɵɵelementStart(
|
|
140
|
+
i0.ɵɵelementStart(4, "span", 49);
|
|
141
141
|
i0.ɵɵtext(5);
|
|
142
|
-
i0.ɵɵ
|
|
143
|
-
i0.ɵɵelementStart(6, "span", 50);
|
|
144
|
-
i0.ɵɵtext(7);
|
|
145
|
-
i0.ɵɵpipe(8, "slice");
|
|
142
|
+
i0.ɵɵpipe(6, "slice");
|
|
146
143
|
i0.ɵɵelementEnd()()();
|
|
147
144
|
} if (rf & 2) {
|
|
148
145
|
const notification_r9 = ctx.$implicit;
|
|
149
|
-
i0.ɵɵadvance(
|
|
146
|
+
i0.ɵɵadvance(3);
|
|
150
147
|
i0.ɵɵtextInterpolate(notification_r9.Title);
|
|
151
148
|
i0.ɵɵadvance(2);
|
|
152
|
-
i0.ɵɵtextInterpolate2("", i0.ɵɵpipeBind3(
|
|
149
|
+
i0.ɵɵtextInterpolate2("", i0.ɵɵpipeBind3(6, 3, notification_r9.Message, 0, 40), "", ((notification_r9.Message == null ? null : notification_r9.Message.length) || 0) > 40 ? "..." : "");
|
|
153
150
|
} }
|
|
154
151
|
function HomeDashboardComponent_Conditional_10_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
155
152
|
i0.ɵɵelementStart(0, "div", 37)(1, "h4", 41);
|
|
@@ -159,7 +156,7 @@ function HomeDashboardComponent_Conditional_10_Conditional_8_Template(rf, ctx) {
|
|
|
159
156
|
i0.ɵɵtext(5);
|
|
160
157
|
i0.ɵɵelementEnd()();
|
|
161
158
|
i0.ɵɵelementStart(6, "div", 44);
|
|
162
|
-
i0.ɵɵrepeaterCreate(7, HomeDashboardComponent_Conditional_10_Conditional_8_For_8_Template,
|
|
159
|
+
i0.ɵɵrepeaterCreate(7, HomeDashboardComponent_Conditional_10_Conditional_8_For_8_Template, 7, 7, "div", 45, i0.ɵɵcomponentInstance().trackByNotification, true);
|
|
163
160
|
i0.ɵɵelementEnd()();
|
|
164
161
|
} if (rf & 2) {
|
|
165
162
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
@@ -170,30 +167,30 @@ function HomeDashboardComponent_Conditional_10_Conditional_8_Template(rf, ctx) {
|
|
|
170
167
|
} }
|
|
171
168
|
function HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
172
169
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
173
|
-
i0.ɵɵelementStart(0, "div",
|
|
170
|
+
i0.ɵɵelementStart(0, "div", 53);
|
|
174
171
|
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_For_2_Template_div_click_0_listener() { const favorite_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.onFavoriteClick(favorite_r11)); });
|
|
175
|
-
i0.ɵɵelementStart(1, "div",
|
|
172
|
+
i0.ɵɵelementStart(1, "div", 54);
|
|
176
173
|
i0.ɵɵelement(2, "i");
|
|
177
174
|
i0.ɵɵelementEnd();
|
|
178
|
-
i0.ɵɵelementStart(3, "div",
|
|
175
|
+
i0.ɵɵelementStart(3, "div", 47)(4, "span", 48);
|
|
179
176
|
i0.ɵɵtext(5);
|
|
180
177
|
i0.ɵɵelementEnd();
|
|
181
|
-
i0.ɵɵelementStart(6, "span",
|
|
178
|
+
i0.ɵɵelementStart(6, "span", 49);
|
|
182
179
|
i0.ɵɵtext(7);
|
|
183
180
|
i0.ɵɵelementEnd()()();
|
|
184
181
|
} if (rf & 2) {
|
|
185
182
|
const favorite_r11 = ctx.$implicit;
|
|
186
183
|
const ctx_r3 = i0.ɵɵnextContext(4);
|
|
187
184
|
i0.ɵɵadvance(2);
|
|
188
|
-
i0.ɵɵclassMap(ctx_r3.
|
|
185
|
+
i0.ɵɵclassMap(ctx_r3.getEntityIconByName(favorite_r11.Entity));
|
|
189
186
|
i0.ɵɵadvance(3);
|
|
190
|
-
i0.ɵɵtextInterpolate(favorite_r11
|
|
187
|
+
i0.ɵɵtextInterpolate(ctx_r3.getFavoriteDisplayName(favorite_r11));
|
|
191
188
|
i0.ɵɵadvance(2);
|
|
192
189
|
i0.ɵɵtextInterpolate(favorite_r11.Entity);
|
|
193
190
|
} }
|
|
194
191
|
function HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
195
192
|
i0.ɵɵelementStart(0, "div", 44);
|
|
196
|
-
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_For_2_Template, 8, 4, "div",
|
|
193
|
+
i0.ɵɵrepeaterCreate(1, HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_For_2_Template, 8, 4, "div", 52, i0.ɵɵcomponentInstance().trackByFavorite, true);
|
|
197
194
|
i0.ɵɵelementEnd();
|
|
198
195
|
} if (rf & 2) {
|
|
199
196
|
const ctx_r3 = i0.ɵɵnextContext(3);
|
|
@@ -201,7 +198,7 @@ function HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_Templ
|
|
|
201
198
|
i0.ɵɵrepeater(ctx_r3.favorites);
|
|
202
199
|
} }
|
|
203
200
|
function HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
204
|
-
i0.ɵɵelementStart(0, "div",
|
|
201
|
+
i0.ɵɵelementStart(0, "div", 51);
|
|
205
202
|
i0.ɵɵelement(1, "i", 55);
|
|
206
203
|
i0.ɵɵelementStart(2, "span");
|
|
207
204
|
i0.ɵɵtext(3, "Loading...");
|
|
@@ -209,11 +206,11 @@ function HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_5_Templ
|
|
|
209
206
|
} }
|
|
210
207
|
function HomeDashboardComponent_Conditional_10_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
211
208
|
i0.ɵɵelementStart(0, "div", 38)(1, "h4", 41);
|
|
212
|
-
i0.ɵɵelement(2, "i",
|
|
209
|
+
i0.ɵɵelement(2, "i", 50);
|
|
213
210
|
i0.ɵɵtext(3, " Favorites ");
|
|
214
211
|
i0.ɵɵelementEnd();
|
|
215
212
|
i0.ɵɵconditionalCreate(4, HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_4_Template, 3, 0, "div", 44);
|
|
216
|
-
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_5_Template, 4, 0, "div",
|
|
213
|
+
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_10_Conditional_9_Conditional_5_Template, 4, 0, "div", 51);
|
|
217
214
|
i0.ɵɵelementEnd();
|
|
218
215
|
} if (rf & 2) {
|
|
219
216
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
@@ -226,20 +223,20 @@ function HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_4_For_
|
|
|
226
223
|
const _r12 = i0.ɵɵgetCurrentView();
|
|
227
224
|
i0.ɵɵelementStart(0, "div", 58);
|
|
228
225
|
i0.ɵɵlistener("click", function HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_4_For_2_Template_div_click_0_listener() { const item_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.onRecentClick(item_r13)); });
|
|
229
|
-
i0.ɵɵelementStart(1, "div",
|
|
226
|
+
i0.ɵɵelementStart(1, "div", 54);
|
|
230
227
|
i0.ɵɵelement(2, "i");
|
|
231
228
|
i0.ɵɵelementEnd();
|
|
232
|
-
i0.ɵɵelementStart(3, "div",
|
|
229
|
+
i0.ɵɵelementStart(3, "div", 47)(4, "span", 48);
|
|
233
230
|
i0.ɵɵtext(5);
|
|
234
231
|
i0.ɵɵelementEnd();
|
|
235
|
-
i0.ɵɵelementStart(6, "span",
|
|
232
|
+
i0.ɵɵelementStart(6, "span", 49);
|
|
236
233
|
i0.ɵɵtext(7);
|
|
237
234
|
i0.ɵɵelementEnd()()();
|
|
238
235
|
} if (rf & 2) {
|
|
239
236
|
const item_r13 = ctx.$implicit;
|
|
240
237
|
const ctx_r3 = i0.ɵɵnextContext(4);
|
|
241
238
|
i0.ɵɵadvance(2);
|
|
242
|
-
i0.ɵɵclassMap(ctx_r3.
|
|
239
|
+
i0.ɵɵclassMap(ctx_r3.getEntityIconByName(item_r13.entityName));
|
|
243
240
|
i0.ɵɵadvance(3);
|
|
244
241
|
i0.ɵɵtextInterpolate(item_r13.recordName || item_r13.recordId);
|
|
245
242
|
i0.ɵɵadvance(2);
|
|
@@ -255,7 +252,7 @@ function HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_4_Temp
|
|
|
255
252
|
i0.ɵɵrepeater(ctx_r3.recentItems);
|
|
256
253
|
} }
|
|
257
254
|
function HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
258
|
-
i0.ɵɵelementStart(0, "div",
|
|
255
|
+
i0.ɵɵelementStart(0, "div", 51);
|
|
259
256
|
i0.ɵɵelement(1, "i", 55);
|
|
260
257
|
i0.ɵɵelementStart(2, "span");
|
|
261
258
|
i0.ɵɵtext(3, "Loading...");
|
|
@@ -267,7 +264,7 @@ function HomeDashboardComponent_Conditional_10_Conditional_10_Template(rf, ctx)
|
|
|
267
264
|
i0.ɵɵtext(3, " Recent ");
|
|
268
265
|
i0.ɵɵelementEnd();
|
|
269
266
|
i0.ɵɵconditionalCreate(4, HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_4_Template, 3, 0, "div", 44);
|
|
270
|
-
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_5_Template, 4, 0, "div",
|
|
267
|
+
i0.ɵɵconditionalCreate(5, HomeDashboardComponent_Conditional_10_Conditional_10_Conditional_5_Template, 4, 0, "div", 51);
|
|
271
268
|
i0.ɵɵelementEnd();
|
|
272
269
|
} if (rf & 2) {
|
|
273
270
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
@@ -367,6 +364,8 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
367
364
|
// Cached icon lookups to avoid repeated method calls
|
|
368
365
|
favoriteIconCache = new Map();
|
|
369
366
|
resourceIconCache = new Map();
|
|
367
|
+
// Resolved display names for favorites (keyed by favorite ID)
|
|
368
|
+
favoriteDisplayNames = new Map();
|
|
370
369
|
/**
|
|
371
370
|
* Check if sidebar has any content to show
|
|
372
371
|
*/
|
|
@@ -492,7 +491,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
492
491
|
this.showConfigDialog = true;
|
|
493
492
|
setTimeout(() => {
|
|
494
493
|
if (this.appConfigDialog) {
|
|
495
|
-
this.appConfigDialog.
|
|
494
|
+
this.appConfigDialog.Open();
|
|
496
495
|
}
|
|
497
496
|
}, 0);
|
|
498
497
|
}
|
|
@@ -537,13 +536,15 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
537
536
|
return item.Label;
|
|
538
537
|
}
|
|
539
538
|
/**
|
|
540
|
-
* Load user favorites from UserInfoEngine (cached)
|
|
539
|
+
* Load user favorites from UserInfoEngine (cached) and resolve record display names
|
|
541
540
|
*/
|
|
542
541
|
async loadFavorites() {
|
|
543
542
|
try {
|
|
544
543
|
this.favoritesLoading = true;
|
|
545
544
|
// Get first 10 favorites (already ordered by __mj_CreatedAt DESC in engine)
|
|
546
545
|
this.favorites = UserInfoEngine.Instance.UserFavorites.slice(0, 10);
|
|
546
|
+
// Batch-resolve record names for all favorites
|
|
547
|
+
await this.resolveFavoriteNames();
|
|
547
548
|
}
|
|
548
549
|
catch (error) {
|
|
549
550
|
console.error('Error loading favorites:', error);
|
|
@@ -553,6 +554,76 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
553
554
|
this.cdr.markForCheck();
|
|
554
555
|
}
|
|
555
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Batch-resolve record display names for favorites using GetEntityRecordNames()
|
|
559
|
+
*/
|
|
560
|
+
async resolveFavoriteNames() {
|
|
561
|
+
const nameInputs = [];
|
|
562
|
+
const favoriteIdByKey = new Map(); // map key -> favorite ID
|
|
563
|
+
for (const fav of this.favorites) {
|
|
564
|
+
if (!fav.Entity || !fav.RecordID)
|
|
565
|
+
continue;
|
|
566
|
+
const compositeKey = this.buildCompositeKeyForRecord(fav.Entity, fav.RecordID);
|
|
567
|
+
if (!compositeKey)
|
|
568
|
+
continue;
|
|
569
|
+
nameInputs.push({ EntityName: fav.Entity, CompositeKey: compositeKey });
|
|
570
|
+
favoriteIdByKey.set(`${fav.Entity}||${compositeKey.ToConcatenatedString()}`, fav.ID);
|
|
571
|
+
}
|
|
572
|
+
if (nameInputs.length === 0)
|
|
573
|
+
return;
|
|
574
|
+
try {
|
|
575
|
+
const nameResults = await this.metadata.GetEntityRecordNames(nameInputs);
|
|
576
|
+
for (const result of nameResults) {
|
|
577
|
+
if (result.Success && result.RecordName) {
|
|
578
|
+
const key = `${result.EntityName}||${result.CompositeKey.ToConcatenatedString()}`;
|
|
579
|
+
const favId = favoriteIdByKey.get(key);
|
|
580
|
+
if (favId) {
|
|
581
|
+
this.favoriteDisplayNames.set(favId, result.RecordName);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
console.warn('Failed to resolve favorite record names:', error);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Build a CompositeKey for a record. RecordID may be stored as either:
|
|
592
|
+
* - Concatenated format: "FieldName|Value" or "Field1|Val1||Field2|Val2"
|
|
593
|
+
* - Plain value: just the raw value (e.g. a GUID)
|
|
594
|
+
*/
|
|
595
|
+
buildCompositeKeyForRecord(entityName, recordId) {
|
|
596
|
+
if (!recordId)
|
|
597
|
+
return null;
|
|
598
|
+
// If recordId contains '|', it's in concatenated format
|
|
599
|
+
if (recordId.includes('|')) {
|
|
600
|
+
try {
|
|
601
|
+
const compositeKey = new CompositeKey();
|
|
602
|
+
compositeKey.LoadFromConcatenatedString(recordId);
|
|
603
|
+
if (compositeKey.KeyValuePairs.length > 0)
|
|
604
|
+
return compositeKey;
|
|
605
|
+
}
|
|
606
|
+
catch {
|
|
607
|
+
// Fall through to entity-based lookup
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
// Plain value — look up entity primary key field(s) to construct the key
|
|
611
|
+
const entityInfo = this.metadata.Entities.find(e => e.Name === entityName);
|
|
612
|
+
if (!entityInfo)
|
|
613
|
+
return null;
|
|
614
|
+
const pkField = entityInfo.FirstPrimaryKey;
|
|
615
|
+
if (!pkField)
|
|
616
|
+
return null;
|
|
617
|
+
const compositeKey = new CompositeKey();
|
|
618
|
+
compositeKey.KeyValuePairs = [{ FieldName: pkField.Name, Value: recordId }];
|
|
619
|
+
return compositeKey;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Get the display name for a favorite (resolved name or entity name fallback)
|
|
623
|
+
*/
|
|
624
|
+
getFavoriteDisplayName(favorite) {
|
|
625
|
+
return this.favoriteDisplayNames.get(favorite.ID) || favorite.Entity || favorite.RecordID;
|
|
626
|
+
}
|
|
556
627
|
/**
|
|
557
628
|
* Load recent items via the RecentAccessService
|
|
558
629
|
*/
|
|
@@ -630,59 +701,37 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
630
701
|
this.navigationService.OpenDynamicView('MJ: User Notifications');
|
|
631
702
|
}
|
|
632
703
|
/**
|
|
633
|
-
* Get icon for
|
|
704
|
+
* Get icon for an entity by name, using entity metadata Icon field (cached)
|
|
634
705
|
*/
|
|
635
|
-
|
|
636
|
-
if (
|
|
637
|
-
return
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
case 'dashboard':
|
|
645
|
-
icon = 'fa-solid fa-gauge-high';
|
|
646
|
-
break;
|
|
647
|
-
case 'artifact':
|
|
648
|
-
icon = 'fa-solid fa-cube';
|
|
649
|
-
break;
|
|
650
|
-
case 'report':
|
|
651
|
-
icon = 'fa-solid fa-chart-bar';
|
|
652
|
-
break;
|
|
653
|
-
default:
|
|
654
|
-
icon = 'fa-solid fa-file';
|
|
655
|
-
}
|
|
656
|
-
this.resourceIconCache.set(resourceType, icon);
|
|
706
|
+
getEntityIconByName(entityName) {
|
|
707
|
+
if (!entityName)
|
|
708
|
+
return 'fa-solid fa-file';
|
|
709
|
+
const cached = this.resourceIconCache.get(entityName);
|
|
710
|
+
if (cached)
|
|
711
|
+
return cached;
|
|
712
|
+
const entityInfo = this.metadata.Entities.find(e => e.Name === entityName);
|
|
713
|
+
const icon = entityInfo ? this.resolveEntityIcon(entityInfo.Icon) : 'fa-solid fa-file';
|
|
714
|
+
this.resourceIconCache.set(entityName, icon);
|
|
657
715
|
return icon;
|
|
658
716
|
}
|
|
659
717
|
/**
|
|
660
|
-
*
|
|
718
|
+
* Resolve an entity's Icon field to a full Font Awesome class string
|
|
661
719
|
*/
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
720
|
+
resolveEntityIcon(icon) {
|
|
721
|
+
if (!icon)
|
|
722
|
+
return 'fa-solid fa-table';
|
|
723
|
+
// Already has a style prefix
|
|
724
|
+
if (icon.startsWith('fa-solid') || icon.startsWith('fa-regular') ||
|
|
725
|
+
icon.startsWith('fa-light') || icon.startsWith('fa-brands') ||
|
|
726
|
+
icon.startsWith('fa ')) {
|
|
727
|
+
return icon;
|
|
666
728
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
icon = 'fa-solid fa-gauge-high';
|
|
671
|
-
}
|
|
672
|
-
else if (entityName === 'user views') {
|
|
673
|
-
icon = 'fa-solid fa-table';
|
|
674
|
-
}
|
|
675
|
-
else if (entityName === 'reports') {
|
|
676
|
-
icon = 'fa-solid fa-chart-bar';
|
|
729
|
+
// Has fa- prefix but no style
|
|
730
|
+
if (icon.startsWith('fa-')) {
|
|
731
|
+
return `fa-solid ${icon}`;
|
|
677
732
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
}
|
|
681
|
-
else {
|
|
682
|
-
icon = 'fa-solid fa-star';
|
|
683
|
-
}
|
|
684
|
-
this.favoriteIconCache.set(cacheKey, icon);
|
|
685
|
-
return icon;
|
|
733
|
+
// Just an icon name like "table" or "users"
|
|
734
|
+
return `fa-solid fa-${icon}`;
|
|
686
735
|
}
|
|
687
736
|
/**
|
|
688
737
|
* Format a date for display (pure function, safe to call in template)
|
|
@@ -739,7 +788,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
739
788
|
} if (rf & 2) {
|
|
740
789
|
let _t;
|
|
741
790
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.appConfigDialog = _t.first);
|
|
742
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 14, vars: 10, consts: [["appConfigDialog", ""], [1, "home-dashboard"], [1, "main-content"], [1, "home-header"], [1, "greeting-section"], [1, "date"], [1, "loading-container"], [1, "apps-section"], [1, "quick-access-sidebar"], ["title", "Quick Access", 1, "sidebar-fab-toggle"], [3, "
|
|
791
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 14, vars: 10, consts: [["appConfigDialog", ""], [1, "home-dashboard"], [1, "main-content"], [1, "home-header"], [1, "greeting-section"], [1, "date"], [1, "loading-container"], [1, "apps-section"], [1, "quick-access-sidebar"], ["title", "Quick Access", 1, "sidebar-fab-toggle"], [3, "ShowDialogChange", "ConfigSaved", "ShowDialog"], ["text", "Loading your applications...", "size", "large"], [1, "section-title"], [1, "fa-solid", "fa-grid-2"], [1, "apps-grid"], [1, "app-card", 3, "--app-color"], [1, "empty-state"], [1, "app-card", 3, "click"], [1, "app-icon-wrapper"], [1, "app-icon"], [1, "app-info"], [1, "app-name"], [1, "app-description"], [1, "nav-preview"], [1, "app-arrow"], [1, "fa-solid", "fa-arrow-right"], [1, "nav-item-chip"], [1, "more-items"], [1, "empty-icon"], [1, "fa-solid", "fa-folder-open"], ["kendoButton", "", "themeColor", "primary", 3, "click"], [1, "fa-solid", "fa-gear"], [1, "sidebar-header"], [1, "fa-solid", "fa-bolt"], ["title", "Close panel", 1, "sidebar-close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "sidebar-content"], [1, "sidebar-section", "notifications-section"], [1, "sidebar-section", "favorites-section"], [1, "sidebar-section", "recents-section"], [1, "sidebar-empty"], [1, "sidebar-section-title"], [1, "fa-solid", "fa-bell"], [1, "section-badge"], [1, "sidebar-items"], [1, "sidebar-item", "notification-item"], [1, "sidebar-item", "notification-item", 3, "click"], [1, "sidebar-item-info"], [1, "sidebar-item-title"], [1, "sidebar-item-subtitle"], [1, "fa-solid", "fa-star"], [1, "sidebar-loading"], [1, "sidebar-item", "favorite-item"], [1, "sidebar-item", "favorite-item", 3, "click"], [1, "sidebar-item-icon"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "sidebar-item", "recent-item"], [1, "sidebar-item", "recent-item", 3, "click"], [1, "fa-solid", "fa-inbox"], ["title", "Quick Access", 1, "sidebar-fab-toggle", 3, "click"], [1, "fab-badge"]], template: function HomeDashboardComponent_Template(rf, ctx) { if (rf & 1) {
|
|
743
792
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
744
793
|
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div", 4)(4, "h1");
|
|
745
794
|
i0.ɵɵtext(5);
|
|
@@ -753,8 +802,8 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
753
802
|
i0.ɵɵconditionalCreate(10, HomeDashboardComponent_Conditional_10_Template, 12, 4, "div", 8);
|
|
754
803
|
i0.ɵɵconditionalCreate(11, HomeDashboardComponent_Conditional_11_Template, 3, 1, "button", 9);
|
|
755
804
|
i0.ɵɵelementStart(12, "mj-user-app-config", 10, 0);
|
|
756
|
-
i0.ɵɵtwoWayListener("
|
|
757
|
-
i0.ɵɵlistener("
|
|
805
|
+
i0.ɵɵtwoWayListener("ShowDialogChange", function HomeDashboardComponent_Template_mj_user_app_config_ShowDialogChange_12_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.showConfigDialog, $event) || (ctx.showConfigDialog = $event); return i0.ɵɵresetView($event); });
|
|
806
|
+
i0.ɵɵlistener("ConfigSaved", function HomeDashboardComponent_Template_mj_user_app_config_ConfigSaved_12_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onConfigSaved()); });
|
|
758
807
|
i0.ɵɵelementEnd()();
|
|
759
808
|
} if (rf & 2) {
|
|
760
809
|
i0.ɵɵclassProp("sidebar-open", ctx.sidebarOpen && ctx.hasSidebarContent);
|
|
@@ -771,7 +820,7 @@ let HomeDashboardComponent = class HomeDashboardComponent extends BaseResourceCo
|
|
|
771
820
|
i0.ɵɵadvance();
|
|
772
821
|
i0.ɵɵconditional(ctx.hasSidebarContent && !ctx.sidebarOpen ? 11 : -1);
|
|
773
822
|
i0.ɵɵadvance();
|
|
774
|
-
i0.ɵɵtwoWayProperty("
|
|
823
|
+
i0.ɵɵtwoWayProperty("ShowDialog", ctx.showConfigDialog);
|
|
775
824
|
} }, dependencies: [i3.ButtonComponent, i4.UserAppConfigComponent, i5.LoadingComponent, i6.SlicePipe], styles: [".home-dashboard[_ngcontent-%COMP%] {\n display: flex;\n height: 100%;\n background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\n overflow: hidden;\n position: relative;\n}\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 0.3s ease;\n}\n\n\n\n.home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 320px;\n}\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: 32px;\n font-weight: 600;\n color: #212529;\n}\n\n.greeting-section[_ngcontent-%COMP%] .date[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n color: #6c757d;\n}\n\n\n\n.sidebar-fab-toggle[_ngcontent-%COMP%] {\n position: fixed;\n top: 80px; \n\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: 50%;\n background: #1976d2;\n color: white;\n font-size: 20px;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4);\n transition: all 0.2s ease;\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: #1565c0;\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(25, 118, 210, 0.5);\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: #e53935;\n color: white;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\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: #6c757d;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #1976d2;\n}\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: 20px;\n font-weight: 600;\n color: #495057;\n}\n\n.section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6c757d;\n}\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\n.app-card[_ngcontent-%COMP%] {\n --app-color: #757575;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 14px;\n border: 1px solid #e9ecef;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\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: 0 8px 24px rgba(0, 0, 0, 0.1);\n transform: translateY(-3px);\n}\n\n.app-card[_ngcontent-%COMP%]:hover::before {\n opacity: 1;\n}\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: 12px;\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: 22px;\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: white;\n transform: scale(1.1);\n}\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: 17px;\n font-weight: 600;\n color: #212529;\n}\n\n.app-description[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 13px;\n color: #6c757d;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n\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: #f8f9fa;\n border-radius: 5px;\n font-size: 11px;\n color: #495057;\n}\n\n.nav-item-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n color: #6c757d;\n}\n\n.more-items[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #6c757d;\n font-style: italic;\n}\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: 16px;\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.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 24px;\n background: white;\n border-radius: 16px;\n border: 2px dashed #dee2e6;\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: #f8f9fa;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #adb5bd;\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #495057;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n}\n\n.empty-state[_ngcontent-%COMP%] button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n\n\n\n\n.quick-access-sidebar[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 0;\n bottom: 0;\n width: 320px;\n background: white;\n border-left: 1px solid #e9ecef;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.3s ease;\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px rgba(0, 0, 0, 0.08);\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 #e9ecef;\n background: #fafbfc;\n}\n\n.sidebar-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #212529;\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: #1976d2;\n font-size: 14px;\n}\n\n.sidebar-close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: #6c757d;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.sidebar-close-btn[_ngcontent-%COMP%]:hover {\n background: #f1f3f4;\n color: #212529;\n}\n\n.sidebar-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\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: 13px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.notifications-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f57c00;\n}\n\n.favorites-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #ffc107;\n}\n\n.recents-section[_ngcontent-%COMP%] .sidebar-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n}\n\n.section-badge[_ngcontent-%COMP%] {\n background: #e53935;\n color: white;\n font-size: 10px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 8px;\n margin-left: auto;\n}\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: #f8f9fa;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sidebar-item[_ngcontent-%COMP%]:hover {\n background: #e9ecef;\n transform: translateX(4px);\n}\n\n.sidebar-item-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n background: white;\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: 14px;\n color: #6c757d;\n}\n\n.notification-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: #fff3e0;\n}\n\n.notification-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f57c00;\n}\n\n.favorite-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: #fff8e1;\n}\n\n.favorite-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f9a825;\n}\n\n.recent-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] {\n background: #e3f2fd;\n}\n\n.recent-item[_ngcontent-%COMP%] .sidebar-item-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\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: 13px;\n font-weight: 500;\n color: #212529;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #6c757d;\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: #6c757d;\n font-size: 13px;\n padding: 8px 0;\n}\n\n.sidebar-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\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: #adb5bd;\n}\n\n.sidebar-empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n}\n\n.sidebar-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n}\n\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\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: 28px;\n }\n\n \n\n .quick-access-sidebar[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n }\n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%] .main-content[_ngcontent-%COMP%] {\n margin-right: 0;\n }\n\n \n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::after {\n content: '';\n position: fixed;\n top: 60px;\n left: 0;\n right: 320px;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n }\n}\n\n\n\n@media (max-width: 768px) {\n .home-dashboard[_ngcontent-%COMP%] {\n height: auto;\n min-height: 100%;\n overflow: visible;\n }\n\n .main-content[_ngcontent-%COMP%] {\n padding: 20px;\n padding-bottom: 100px; \n\n overflow: visible;\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: 24px;\n }\n\n \n\n .quick-access-sidebar[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 100; \n\n border-left: none;\n border-top: 1px solid #e9ecef;\n }\n\n \n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::before {\n content: '';\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 99;\n }\n\n \n\n .home-dashboard.sidebar-open[_ngcontent-%COMP%]::after {\n display: none;\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: 18px;\n }\n\n .app-name[_ngcontent-%COMP%] {\n font-size: 15px;\n }\n\n .nav-preview[_ngcontent-%COMP%] {\n display: none;\n }\n\n \n\n .sidebar-fab-toggle[_ngcontent-%COMP%] {\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: 18px;\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: 20px;\n }\n\n .greeting-section[_ngcontent-%COMP%] .date[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n\n .section-title[_ngcontent-%COMP%] {\n font-size: 16px;\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: 16px;\n }\n}"], changeDetection: 0 });
|
|
776
825
|
};
|
|
777
826
|
HomeDashboardComponent = __decorate([
|
|
@@ -780,7 +829,7 @@ HomeDashboardComponent = __decorate([
|
|
|
780
829
|
export { HomeDashboardComponent };
|
|
781
830
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(HomeDashboardComponent, [{
|
|
782
831
|
type: Component,
|
|
783
|
-
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 <!-- 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 Your Applications\n </h2>\n <div class=\"apps-grid\">\n @for (appData of appsDisplayData; track trackByApp($index, appData)) {\n <div\n class=\"app-card\"\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 <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <h3>No Applications Available</h3>\n <p>You don't have any applications configured yet.</p>\n <button kendoButton\n themeColor=\"primary\"\n (click)=\"openConfigDialog()\">\n <i class=\"fa-solid fa-gear\"></i>\n Configure Applications\n </button>\n </div>\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 (click)=\"onNotificationClick(notification)\">\n <div class=\"sidebar-item-icon\">\n <i class=\"fa-solid fa-bell\"></i>\n </div>\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 (click)=\"onFavoriteClick(favorite)\">\n <div class=\"sidebar-item-icon\">\n <i [class]=\"getFavoriteIcon(favorite)\"></i>\n </div>\n <div class=\"sidebar-item-info\">\n <span class=\"sidebar-item-title\">{{ favorite.RecordID }}</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 (click)=\"onRecentClick(item)\">\n <div class=\"sidebar-item-icon\">\n <i [class]=\"getResourceIcon(item.resourceType)\"></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 <div class=\"sidebar-empty\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No quick access items</p>\n </div>\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: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\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 0.3s ease;\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: 32px;\n font-weight: 600;\n color: #212529;\n}\n\n.greeting-section .date {\n margin: 0;\n font-size: 16px;\n color: #6c757d;\n}\n\n/* FAB Toggle Button for Quick Access - top-right on desktop */\n.sidebar-fab-toggle {\n position: fixed;\n top: 80px; /* Below shell header with some spacing */\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: 50%;\n background: #1976d2;\n color: white;\n font-size: 20px;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4);\n transition: all 0.2s ease;\n z-index: 100;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sidebar-fab-toggle:hover {\n background: #1565c0;\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(25, 118, 210, 0.5);\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: #e53935;\n color: white;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\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: #6c757d;\n}\n\n.loading-spinner {\n font-size: 32px;\n color: #1976d2;\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: 20px;\n font-weight: 600;\n color: #495057;\n}\n\n.section-title i {\n color: #6c757d;\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: #757575;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 14px;\n border: 1px solid #e9ecef;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\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: 0 8px 24px rgba(0, 0, 0, 0.1);\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: 12px;\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: 22px;\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: white;\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: 17px;\n font-weight: 600;\n color: #212529;\n}\n\n.app-description {\n margin: 0 0 10px 0;\n font-size: 13px;\n color: #6c757d;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* 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: #f8f9fa;\n border-radius: 5px;\n font-size: 11px;\n color: #495057;\n}\n\n.nav-item-chip i {\n font-size: 9px;\n color: #6c757d;\n}\n\n.more-items {\n font-size: 11px;\n color: #6c757d;\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: 16px;\n}\n\n.app-card:hover .app-arrow {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 24px;\n background: white;\n border-radius: 16px;\n border: 2px dashed #dee2e6;\n text-align: center;\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: #f8f9fa;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.empty-icon i {\n font-size: 32px;\n color: #adb5bd;\n}\n\n.empty-state h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #495057;\n}\n\n.empty-state p {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n}\n\n.empty-state button i {\n margin-right: 8px;\n}\n\n/* ========================================\n RIGHT SIDEBAR\n ======================================== */\n.quick-access-sidebar {\n position: fixed;\n top: 60px; /* Below shell header */\n right: 0;\n bottom: 0;\n width: 320px;\n background: white;\n border-left: 1px solid #e9ecef;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.3s ease;\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px rgba(0, 0, 0, 0.08);\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 #e9ecef;\n background: #fafbfc;\n}\n\n.sidebar-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sidebar-header h3 i {\n color: #1976d2;\n font-size: 14px;\n}\n\n.sidebar-close-btn {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: #6c757d;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.sidebar-close-btn:hover {\n background: #f1f3f4;\n color: #212529;\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: 13px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title i {\n font-size: 12px;\n}\n\n.notifications-section .sidebar-section-title i {\n color: #f57c00;\n}\n\n.favorites-section .sidebar-section-title i {\n color: #ffc107;\n}\n\n.recents-section .sidebar-section-title i {\n color: #1976d2;\n}\n\n.section-badge {\n background: #e53935;\n color: white;\n font-size: 10px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 8px;\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: #f8f9fa;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sidebar-item:hover {\n background: #e9ecef;\n transform: translateX(4px);\n}\n\n.sidebar-item-icon {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n background: white;\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: 14px;\n color: #6c757d;\n}\n\n.notification-item .sidebar-item-icon {\n background: #fff3e0;\n}\n\n.notification-item .sidebar-item-icon i {\n color: #f57c00;\n}\n\n.favorite-item .sidebar-item-icon {\n background: #fff8e1;\n}\n\n.favorite-item .sidebar-item-icon i {\n color: #f9a825;\n}\n\n.recent-item .sidebar-item-icon {\n background: #e3f2fd;\n}\n\n.recent-item .sidebar-item-icon i {\n color: #1976d2;\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: 13px;\n font-weight: 500;\n color: #212529;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle {\n font-size: 11px;\n color: #6c757d;\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: #6c757d;\n font-size: 13px;\n padding: 8px 0;\n}\n\n.sidebar-loading i {\n color: #1976d2;\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: #adb5bd;\n}\n\n.sidebar-empty i {\n font-size: 32px;\n margin-bottom: 12px;\n}\n\n.sidebar-empty p {\n margin: 0;\n font-size: 13px;\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: 28px;\n }\n\n /* Make sidebar an overlay on tablet */\n .quick-access-sidebar {\n position: fixed;\n top: 60px; /* Below shell header */\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\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: fixed;\n top: 60px;\n left: 0;\n right: 320px;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .home-dashboard {\n height: auto;\n min-height: 100%;\n overflow: visible;\n }\n\n .main-content {\n padding: 20px;\n padding-bottom: 100px; /* Space for FAB button */\n overflow: visible;\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: 24px;\n }\n\n /* Full-width sidebar on mobile - positioned below top nav */\n .quick-access-sidebar {\n position: fixed;\n top: 60px; /* Below the shell header */\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 100; /* Below shell header */\n border-left: none;\n border-top: 1px solid #e9ecef;\n }\n\n /* Add backdrop on mobile when sidebar is open */\n .home-dashboard.sidebar-open::before {\n content: '';\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 99;\n }\n\n /* No ::after backdrop needed on mobile */\n .home-dashboard.sidebar-open::after {\n display: none;\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: 18px;\n }\n\n .app-name {\n font-size: 15px;\n }\n\n .nav-preview {\n display: none;\n }\n\n /* Move FAB to bottom-right on mobile */\n .sidebar-fab-toggle {\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: 18px;\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: 20px;\n }\n\n .greeting-section .date {\n font-size: 14px;\n }\n\n .section-title {\n font-size: 16px;\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: 16px;\n }\n}\n"] }]
|
|
832
|
+
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 <!-- 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 Your Applications\n </h2>\n <div class=\"apps-grid\">\n @for (appData of appsDisplayData; track trackByApp($index, appData)) {\n <div\n class=\"app-card\"\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 <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-folder-open\"></i>\n </div>\n <h3>No Applications Available</h3>\n <p>You don't have any applications configured yet.</p>\n <button kendoButton\n themeColor=\"primary\"\n (click)=\"openConfigDialog()\">\n <i class=\"fa-solid fa-gear\"></i>\n Configure Applications\n </button>\n </div>\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 (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 (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 (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 <div class=\"sidebar-empty\">\n <i class=\"fa-solid fa-inbox\"></i>\n <p>No quick access items</p>\n </div>\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: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\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 0.3s ease;\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: 32px;\n font-weight: 600;\n color: #212529;\n}\n\n.greeting-section .date {\n margin: 0;\n font-size: 16px;\n color: #6c757d;\n}\n\n/* FAB Toggle Button for Quick Access - top-right on desktop */\n.sidebar-fab-toggle {\n position: fixed;\n top: 80px; /* Below shell header with some spacing */\n right: 24px;\n width: 56px;\n height: 56px;\n border: none;\n border-radius: 50%;\n background: #1976d2;\n color: white;\n font-size: 20px;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4);\n transition: all 0.2s ease;\n z-index: 100;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sidebar-fab-toggle:hover {\n background: #1565c0;\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(25, 118, 210, 0.5);\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: #e53935;\n color: white;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\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: #6c757d;\n}\n\n.loading-spinner {\n font-size: 32px;\n color: #1976d2;\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: 20px;\n font-weight: 600;\n color: #495057;\n}\n\n.section-title i {\n color: #6c757d;\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: #757575;\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 20px;\n background: white;\n border-radius: 14px;\n border: 1px solid #e9ecef;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\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: 0 8px 24px rgba(0, 0, 0, 0.1);\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: 12px;\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: 22px;\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: white;\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: 17px;\n font-weight: 600;\n color: #212529;\n}\n\n.app-description {\n margin: 0 0 10px 0;\n font-size: 13px;\n color: #6c757d;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* 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: #f8f9fa;\n border-radius: 5px;\n font-size: 11px;\n color: #495057;\n}\n\n.nav-item-chip i {\n font-size: 9px;\n color: #6c757d;\n}\n\n.more-items {\n font-size: 11px;\n color: #6c757d;\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: 16px;\n}\n\n.app-card:hover .app-arrow {\n opacity: 1;\n transform: translateY(-50%) translateX(0);\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 24px;\n background: white;\n border-radius: 16px;\n border: 2px dashed #dee2e6;\n text-align: center;\n}\n\n.empty-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: #f8f9fa;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.empty-icon i {\n font-size: 32px;\n color: #adb5bd;\n}\n\n.empty-state h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #495057;\n}\n\n.empty-state p {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n}\n\n.empty-state button i {\n margin-right: 8px;\n}\n\n/* ========================================\n RIGHT SIDEBAR\n ======================================== */\n.quick-access-sidebar {\n position: fixed;\n top: 60px; /* Below shell header */\n right: 0;\n bottom: 0;\n width: 320px;\n background: white;\n border-left: 1px solid #e9ecef;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.3s ease;\n overflow: hidden;\n z-index: 100;\n box-shadow: -2px 0 8px rgba(0, 0, 0, 0.08);\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 #e9ecef;\n background: #fafbfc;\n}\n\n.sidebar-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sidebar-header h3 i {\n color: #1976d2;\n font-size: 14px;\n}\n\n.sidebar-close-btn {\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: #6c757d;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.sidebar-close-btn:hover {\n background: #f1f3f4;\n color: #212529;\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: 13px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.sidebar-section-title i {\n font-size: 12px;\n}\n\n.notifications-section .sidebar-section-title i {\n color: #f57c00;\n}\n\n.favorites-section .sidebar-section-title i {\n color: #ffc107;\n}\n\n.recents-section .sidebar-section-title i {\n color: #1976d2;\n}\n\n.section-badge {\n background: #e53935;\n color: white;\n font-size: 10px;\n font-weight: 600;\n padding: 2px 6px;\n border-radius: 8px;\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: #f8f9fa;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sidebar-item:hover {\n background: #e9ecef;\n transform: translateX(4px);\n}\n\n.sidebar-item-icon {\n width: 36px;\n height: 36px;\n border-radius: 8px;\n background: white;\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: 14px;\n color: #6c757d;\n}\n\n.notification-item .sidebar-item-icon {\n background: #fff3e0;\n}\n\n.notification-item .sidebar-item-icon i {\n color: #f57c00;\n}\n\n.favorite-item .sidebar-item-icon {\n background: #fff8e1;\n}\n\n.favorite-item .sidebar-item-icon i {\n color: #f9a825;\n}\n\n.recent-item .sidebar-item-icon {\n background: #e3f2fd;\n}\n\n.recent-item .sidebar-item-icon i {\n color: #1976d2;\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: 13px;\n font-weight: 500;\n color: #212529;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebar-item-subtitle {\n font-size: 11px;\n color: #6c757d;\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: #6c757d;\n font-size: 13px;\n padding: 8px 0;\n}\n\n.sidebar-loading i {\n color: #1976d2;\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: #adb5bd;\n}\n\n.sidebar-empty i {\n font-size: 32px;\n margin-bottom: 12px;\n}\n\n.sidebar-empty p {\n margin: 0;\n font-size: 13px;\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: 28px;\n }\n\n /* Make sidebar an overlay on tablet */\n .quick-access-sidebar {\n position: fixed;\n top: 60px; /* Below shell header */\n right: 0;\n bottom: 0;\n width: 320px;\n z-index: 1000;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\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: fixed;\n top: 60px;\n left: 0;\n right: 320px;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n }\n}\n\n/* Mobile */\n@media (max-width: 768px) {\n .home-dashboard {\n height: auto;\n min-height: 100%;\n overflow: visible;\n }\n\n .main-content {\n padding: 20px;\n padding-bottom: 100px; /* Space for FAB button */\n overflow: visible;\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: 24px;\n }\n\n /* Full-width sidebar on mobile - positioned below top nav */\n .quick-access-sidebar {\n position: fixed;\n top: 60px; /* Below the shell header */\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n z-index: 100; /* Below shell header */\n border-left: none;\n border-top: 1px solid #e9ecef;\n }\n\n /* Add backdrop on mobile when sidebar is open */\n .home-dashboard.sidebar-open::before {\n content: '';\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 99;\n }\n\n /* No ::after backdrop needed on mobile */\n .home-dashboard.sidebar-open::after {\n display: none;\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: 18px;\n }\n\n .app-name {\n font-size: 15px;\n }\n\n .nav-preview {\n display: none;\n }\n\n /* Move FAB to bottom-right on mobile */\n .sidebar-fab-toggle {\n top: auto;\n bottom: 20px;\n right: 20px;\n width: 48px;\n height: 48px;\n font-size: 18px;\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: 20px;\n }\n\n .greeting-section .date {\n font-size: 14px;\n }\n\n .section-title {\n font-size: 16px;\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: 16px;\n }\n}\n"] }]
|
|
784
833
|
}], () => [{ type: i1.ApplicationManager }, { type: i2.NavigationService }, { type: i2.RecentAccessService }, { type: i0.ChangeDetectorRef }], { appConfigDialog: [{
|
|
785
834
|
type: ViewChild,
|
|
786
835
|
args: ['appConfigDialog']
|