@memberjunction/ng-explorer-core 5.43.0 → 5.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +15 -3
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/about/about-dialog.component.d.ts +0 -1
- package/dist/lib/about/about-dialog.component.d.ts.map +1 -1
- package/dist/lib/about/about-dialog.component.js +217 -218
- package/dist/lib/about/about-dialog.component.js.map +1 -1
- package/dist/lib/command-palette/command-palette.component.js +8 -14
- package/dist/lib/command-palette/command-palette.component.js.map +1 -1
- package/dist/lib/conversation-feedback/conversation-feedback.js +66 -73
- package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +35 -45
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +6 -4
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +33 -17
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +9 -8
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +35 -43
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-switcher.component.d.ts +6 -1
- package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-switcher.component.js +6 -3
- package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +10 -2
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +19 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +1 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +3 -2
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +1 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +4 -1
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +5 -7
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +17 -27
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts +6 -2
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +48 -57
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.js +17 -22
- package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.d.ts +65 -9
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +441 -261
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/module.d.ts +33 -32
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +18 -7
- package/dist/module.js.map +1 -1
- package/package.json +49 -47
- package/dist/lib/__tests__/explorer-core.test.d.ts +0 -2
- package/dist/lib/__tests__/explorer-core.test.d.ts.map +0 -1
- package/dist/lib/__tests__/explorer-core.test.js +0 -229
- package/dist/lib/__tests__/explorer-core.test.js.map +0 -1
|
@@ -1,87 +1,102 @@
|
|
|
1
|
-
import { Component,
|
|
1
|
+
import { Component, ChangeDetectorRef, inject } from '@angular/core';
|
|
2
2
|
import { SharedService } from '@memberjunction/ng-shared';
|
|
3
3
|
import { MJUserNotificationEntity, UserInfoEngine } from '@memberjunction/core-entities';
|
|
4
|
-
import {
|
|
4
|
+
import { CompositeKey } from '@memberjunction/core';
|
|
5
5
|
import { SafeJSONParse, UUIDsEqual } from '@memberjunction/global';
|
|
6
6
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
7
7
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
8
8
|
import * as i0 from "@angular/core";
|
|
9
9
|
import * as i1 from "@memberjunction/ng-shared";
|
|
10
10
|
import * as i2 from "@memberjunction/ng-base-application";
|
|
11
|
-
import * as i3 from "@
|
|
12
|
-
import * as i4 from "@angular/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const _c2 = ["readRadio"];
|
|
11
|
+
import * as i3 from "@memberjunction/ng-markdown";
|
|
12
|
+
import * as i4 from "@angular/forms";
|
|
13
|
+
import * as i5 from "@memberjunction/ng-ui-components";
|
|
14
|
+
import * as i6 from "@angular/common";
|
|
16
15
|
const _forTrack0 = ($index, $item) => $item.ID;
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const _forTrack1 = ($index, $item) => $item.Key;
|
|
17
|
+
const _forTrack2 = ($index, $item) => $item.N.ID;
|
|
18
|
+
function UserNotificationsComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
19
|
+
i0.ɵɵelementStart(0, "span", 7);
|
|
20
|
+
i0.ɵɵtext(1);
|
|
21
|
+
i0.ɵɵelementEnd();
|
|
22
|
+
} if (rf & 2) {
|
|
23
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
24
|
+
i0.ɵɵadvance();
|
|
25
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.UnreadNotifications.length, " unread");
|
|
26
|
+
} }
|
|
27
|
+
function UserNotificationsComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
28
|
+
i0.ɵɵelementStart(0, "span", 7);
|
|
29
|
+
i0.ɵɵtext(1, "All caught up");
|
|
30
|
+
i0.ɵɵelementEnd();
|
|
31
|
+
} }
|
|
32
|
+
function UserNotificationsComponent_Conditional_11_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
33
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
19
34
|
i0.ɵɵelementStart(0, "button", 16);
|
|
20
|
-
i0.ɵɵlistener("click", function
|
|
35
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_11_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.markAllAsRead()); });
|
|
21
36
|
i0.ɵɵelement(1, "i", 17);
|
|
22
37
|
i0.ɵɵelementStart(2, "span", 18);
|
|
23
38
|
i0.ɵɵtext(3, "Mark All Read");
|
|
24
39
|
i0.ɵɵelementEnd()();
|
|
25
40
|
} }
|
|
26
|
-
function
|
|
41
|
+
function UserNotificationsComponent_Conditional_11_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
27
42
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
28
43
|
i0.ɵɵelementStart(0, "button", 19);
|
|
29
|
-
i0.ɵɵlistener("click", function
|
|
44
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_11_Conditional_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.markAllAsUnread()); });
|
|
30
45
|
i0.ɵɵelement(1, "i", 20);
|
|
31
46
|
i0.ɵɵelementStart(2, "span", 18);
|
|
32
47
|
i0.ɵɵtext(3, "Mark All Unread");
|
|
33
48
|
i0.ɵɵelementEnd()();
|
|
34
49
|
} }
|
|
35
|
-
function
|
|
36
|
-
i0.ɵɵelementStart(0, "div",
|
|
37
|
-
i0.ɵɵconditionalCreate(1,
|
|
38
|
-
i0.ɵɵconditionalCreate(2,
|
|
50
|
+
function UserNotificationsComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
51
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
52
|
+
i0.ɵɵconditionalCreate(1, UserNotificationsComponent_Conditional_11_Conditional_1_Template, 4, 0, "button", 14);
|
|
53
|
+
i0.ɵɵconditionalCreate(2, UserNotificationsComponent_Conditional_11_Conditional_2_Template, 4, 0, "button", 15);
|
|
39
54
|
i0.ɵɵelementEnd();
|
|
40
55
|
} if (rf & 2) {
|
|
41
|
-
const
|
|
56
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
42
57
|
i0.ɵɵadvance();
|
|
43
|
-
i0.ɵɵconditional(
|
|
58
|
+
i0.ɵɵconditional(ctx_r0.UnreadNotifications.length > 0 ? 1 : -1);
|
|
44
59
|
i0.ɵɵadvance();
|
|
45
|
-
i0.ɵɵconditional(
|
|
60
|
+
i0.ɵɵconditional(ctx_r0.ReadNotifications.length > 0 ? 2 : -1);
|
|
46
61
|
} }
|
|
47
|
-
function
|
|
62
|
+
function UserNotificationsComponent_Conditional_12_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
48
63
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
49
|
-
i0.ɵɵelementStart(0, "button",
|
|
50
|
-
i0.ɵɵlistener("click", function
|
|
51
|
-
i0.ɵɵelementStart(1, "span",
|
|
64
|
+
i0.ɵɵelementStart(0, "button", 35);
|
|
65
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_12_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.selectReadOption("Unread")); });
|
|
66
|
+
i0.ɵɵelementStart(1, "span", 25);
|
|
52
67
|
i0.ɵɵtext(2, "Unread");
|
|
53
68
|
i0.ɵɵelementEnd();
|
|
54
|
-
i0.ɵɵelementStart(3, "span",
|
|
69
|
+
i0.ɵɵelementStart(3, "span", 26);
|
|
55
70
|
i0.ɵɵtext(4);
|
|
56
71
|
i0.ɵɵelementEnd()();
|
|
57
72
|
} if (rf & 2) {
|
|
58
|
-
const
|
|
59
|
-
i0.ɵɵclassProp("active",
|
|
60
|
-
i0.ɵɵattribute("aria-pressed",
|
|
73
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
74
|
+
i0.ɵɵclassProp("active", ctx_r0.radioSelected === "Unread")("has-unread", ctx_r0.UnreadNotifications.length > 0);
|
|
75
|
+
i0.ɵɵattribute("aria-pressed", ctx_r0.radioSelected === "Unread");
|
|
61
76
|
i0.ɵɵadvance(3);
|
|
62
|
-
i0.ɵɵclassProp("unread-count",
|
|
77
|
+
i0.ɵɵclassProp("unread-count", ctx_r0.UnreadNotifications.length > 0);
|
|
63
78
|
i0.ɵɵadvance();
|
|
64
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
79
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.UnreadNotifications.length, " ");
|
|
65
80
|
} }
|
|
66
|
-
function
|
|
81
|
+
function UserNotificationsComponent_Conditional_12_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
67
82
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
68
|
-
i0.ɵɵelementStart(0, "button",
|
|
69
|
-
i0.ɵɵlistener("click", function
|
|
70
|
-
i0.ɵɵelementStart(1, "span",
|
|
83
|
+
i0.ɵɵelementStart(0, "button", 36);
|
|
84
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_12_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.selectReadOption("Read")); });
|
|
85
|
+
i0.ɵɵelementStart(1, "span", 25);
|
|
71
86
|
i0.ɵɵtext(2, "Read");
|
|
72
87
|
i0.ɵɵelementEnd();
|
|
73
|
-
i0.ɵɵelementStart(3, "span",
|
|
88
|
+
i0.ɵɵelementStart(3, "span", 26);
|
|
74
89
|
i0.ɵɵtext(4);
|
|
75
90
|
i0.ɵɵelementEnd()();
|
|
76
91
|
} if (rf & 2) {
|
|
77
|
-
const
|
|
78
|
-
i0.ɵɵclassProp("active",
|
|
79
|
-
i0.ɵɵattribute("aria-pressed",
|
|
92
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
93
|
+
i0.ɵɵclassProp("active", ctx_r0.radioSelected === "Read");
|
|
94
|
+
i0.ɵɵattribute("aria-pressed", ctx_r0.radioSelected === "Read");
|
|
80
95
|
i0.ɵɵadvance(4);
|
|
81
|
-
i0.ɵɵtextInterpolate(
|
|
96
|
+
i0.ɵɵtextInterpolate(ctx_r0.ReadNotifications.length);
|
|
82
97
|
} }
|
|
83
|
-
function
|
|
84
|
-
i0.ɵɵelementStart(0, "option",
|
|
98
|
+
function UserNotificationsComponent_Conditional_12_Conditional_11_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
99
|
+
i0.ɵɵelementStart(0, "option", 38);
|
|
85
100
|
i0.ɵɵtext(1);
|
|
86
101
|
i0.ɵɵelementEnd();
|
|
87
102
|
} if (rf & 2) {
|
|
@@ -90,205 +105,281 @@ function UserNotificationsComponent_Conditional_9_Conditional_17_For_5_Template(
|
|
|
90
105
|
i0.ɵɵadvance();
|
|
91
106
|
i0.ɵɵtextInterpolate(type_r8.Name);
|
|
92
107
|
} }
|
|
93
|
-
function
|
|
108
|
+
function UserNotificationsComponent_Conditional_12_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
94
109
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
95
|
-
i0.ɵɵelementStart(0, "div",
|
|
96
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
97
|
-
i0.ɵɵlistener("change", function
|
|
98
|
-
i0.ɵɵelementStart(2, "option",
|
|
110
|
+
i0.ɵɵelementStart(0, "div", 29)(1, "select", 37);
|
|
111
|
+
i0.ɵɵtwoWayListener("ngModelChange", function UserNotificationsComponent_Conditional_12_Conditional_11_Template_select_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.selectedTypeFilter, $event) || (ctx_r0.selectedTypeFilter = $event); return i0.ɵɵresetView($event); });
|
|
112
|
+
i0.ɵɵlistener("change", function UserNotificationsComponent_Conditional_12_Conditional_11_Template_select_change_1_listener() { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onTypeFilterChange(ctx_r0.selectedTypeFilter)); });
|
|
113
|
+
i0.ɵɵelementStart(2, "option", 38);
|
|
99
114
|
i0.ɵɵtext(3, "All Types");
|
|
100
115
|
i0.ɵɵelementEnd();
|
|
101
|
-
i0.ɵɵrepeaterCreate(4,
|
|
116
|
+
i0.ɵɵrepeaterCreate(4, UserNotificationsComponent_Conditional_12_Conditional_11_For_5_Template, 2, 2, "option", 38, _forTrack0);
|
|
102
117
|
i0.ɵɵelementEnd()();
|
|
103
118
|
} if (rf & 2) {
|
|
104
|
-
const
|
|
119
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
105
120
|
i0.ɵɵadvance();
|
|
106
|
-
i0.ɵɵtwoWayProperty("ngModel",
|
|
121
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.selectedTypeFilter);
|
|
107
122
|
i0.ɵɵadvance();
|
|
108
123
|
i0.ɵɵproperty("value", null);
|
|
109
124
|
i0.ɵɵadvance(2);
|
|
110
|
-
i0.ɵɵrepeater(
|
|
125
|
+
i0.ɵɵrepeater(ctx_r0.notificationTypes);
|
|
111
126
|
} }
|
|
112
|
-
function
|
|
113
|
-
i0.ɵɵelementStart(0, "div",
|
|
114
|
-
i0.ɵɵelement(2, "i",
|
|
127
|
+
function UserNotificationsComponent_Conditional_12_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
128
|
+
i0.ɵɵelementStart(0, "div", 34)(1, "span", 39);
|
|
129
|
+
i0.ɵɵelement(2, "i", 40);
|
|
115
130
|
i0.ɵɵtext(3);
|
|
116
131
|
i0.ɵɵelementEnd()();
|
|
117
132
|
} if (rf & 2) {
|
|
118
|
-
const
|
|
133
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
119
134
|
i0.ɵɵadvance(3);
|
|
120
|
-
i0.ɵɵtextInterpolate2(" Showing ",
|
|
135
|
+
i0.ɵɵtextInterpolate2(" Showing ", ctx_r0.NotificationsToShow.length, " of ", ctx_r0.AllNotifications.length, " ");
|
|
121
136
|
} }
|
|
122
|
-
function
|
|
137
|
+
function UserNotificationsComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
123
138
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
124
|
-
i0.ɵɵelementStart(0, "div",
|
|
125
|
-
i0.ɵɵlistener("
|
|
139
|
+
i0.ɵɵelementStart(0, "div", 9)(1, "div", 21)(2, "div", 22)(3, "div", 23)(4, "button", 24);
|
|
140
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_12_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.selectReadOption("All")); });
|
|
141
|
+
i0.ɵɵelementStart(5, "span", 25);
|
|
142
|
+
i0.ɵɵtext(6, "All");
|
|
126
143
|
i0.ɵɵelementEnd();
|
|
127
|
-
i0.ɵɵelementStart(6, "button", 25);
|
|
128
|
-
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_9_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.selectReadOption("All")); });
|
|
129
144
|
i0.ɵɵelementStart(7, "span", 26);
|
|
130
|
-
i0.ɵɵtext(8
|
|
131
|
-
i0.ɵɵelementEnd();
|
|
132
|
-
i0.ɵɵelementStart(9, "span", 27);
|
|
133
|
-
i0.ɵɵtext(10);
|
|
145
|
+
i0.ɵɵtext(8);
|
|
134
146
|
i0.ɵɵelementEnd()();
|
|
135
|
-
i0.ɵɵ
|
|
136
|
-
i0.ɵɵ
|
|
147
|
+
i0.ɵɵconditionalCreate(9, UserNotificationsComponent_Conditional_12_Conditional_9_Template, 5, 8, "button", 27);
|
|
148
|
+
i0.ɵɵconditionalCreate(10, UserNotificationsComponent_Conditional_12_Conditional_10_Template, 5, 4, "button", 28);
|
|
137
149
|
i0.ɵɵelementEnd();
|
|
138
|
-
i0.ɵɵconditionalCreate(
|
|
139
|
-
i0.ɵɵelementStart(14, "input", 30, 2);
|
|
140
|
-
i0.ɵɵlistener("change", function UserNotificationsComponent_Conditional_9_Template_input_change_14_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onReadRadioChanged($event)); });
|
|
141
|
-
i0.ɵɵelementEnd();
|
|
142
|
-
i0.ɵɵconditionalCreate(16, UserNotificationsComponent_Conditional_9_Conditional_16_Template, 5, 4, "button", 31);
|
|
143
|
-
i0.ɵɵelementEnd();
|
|
144
|
-
i0.ɵɵconditionalCreate(17, UserNotificationsComponent_Conditional_9_Conditional_17_Template, 6, 2, "div", 32);
|
|
150
|
+
i0.ɵɵconditionalCreate(11, UserNotificationsComponent_Conditional_12_Conditional_11_Template, 6, 2, "div", 29);
|
|
145
151
|
i0.ɵɵelementEnd()();
|
|
146
|
-
i0.ɵɵelementStart(
|
|
147
|
-
i0.ɵɵelement(
|
|
148
|
-
i0.ɵɵelementStart(
|
|
149
|
-
i0.ɵɵlistener("input", function
|
|
152
|
+
i0.ɵɵelementStart(12, "div", 30)(13, "div", 31);
|
|
153
|
+
i0.ɵɵelement(14, "i", 32);
|
|
154
|
+
i0.ɵɵelementStart(15, "input", 33);
|
|
155
|
+
i0.ɵɵlistener("input", function UserNotificationsComponent_Conditional_12_Template_input_input_15_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onFilterChanged($event.target.value)); });
|
|
150
156
|
i0.ɵɵelementEnd()()();
|
|
151
|
-
i0.ɵɵconditionalCreate(
|
|
157
|
+
i0.ɵɵconditionalCreate(16, UserNotificationsComponent_Conditional_12_Conditional_16_Template, 4, 2, "div", 34);
|
|
152
158
|
i0.ɵɵelementEnd();
|
|
153
159
|
} if (rf & 2) {
|
|
154
|
-
const
|
|
155
|
-
i0.ɵɵadvance(6);
|
|
156
|
-
i0.ɵɵclassProp("active", ctx_r1.radioSelected === "All");
|
|
157
|
-
i0.ɵɵattribute("aria-pressed", ctx_r1.radioSelected === "All");
|
|
160
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
158
161
|
i0.ɵɵadvance(4);
|
|
159
|
-
i0.ɵɵ
|
|
160
|
-
i0.ɵɵ
|
|
161
|
-
i0.ɵɵ
|
|
162
|
-
i0.ɵɵ
|
|
163
|
-
i0.ɵɵ
|
|
162
|
+
i0.ɵɵclassProp("active", ctx_r0.radioSelected === "All");
|
|
163
|
+
i0.ɵɵattribute("aria-pressed", ctx_r0.radioSelected === "All");
|
|
164
|
+
i0.ɵɵadvance(4);
|
|
165
|
+
i0.ɵɵtextInterpolate(ctx_r0.AllNotifications.length);
|
|
166
|
+
i0.ɵɵadvance();
|
|
167
|
+
i0.ɵɵconditional(ctx_r0.UnreadNotifications.length > 0 || ctx_r0.ReadNotifications.length === 0 ? 9 : -1);
|
|
164
168
|
i0.ɵɵadvance();
|
|
165
|
-
i0.ɵɵconditional(
|
|
169
|
+
i0.ɵɵconditional(ctx_r0.ReadNotifications.length > 0 || ctx_r0.UnreadNotifications.length === 0 ? 10 : -1);
|
|
170
|
+
i0.ɵɵadvance();
|
|
171
|
+
i0.ɵɵconditional(ctx_r0.notificationTypes.length > 0 ? 11 : -1);
|
|
166
172
|
i0.ɵɵadvance(4);
|
|
167
|
-
i0.ɵɵproperty("value",
|
|
173
|
+
i0.ɵɵproperty("value", ctx_r0.currentFilter);
|
|
168
174
|
i0.ɵɵadvance();
|
|
169
|
-
i0.ɵɵconditional(
|
|
175
|
+
i0.ɵɵconditional(ctx_r0.NotificationsToShow.length !== ctx_r0.AllNotifications.length ? 16 : -1);
|
|
170
176
|
} }
|
|
171
|
-
function
|
|
172
|
-
i0.ɵɵ
|
|
173
|
-
|
|
177
|
+
function UserNotificationsComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
178
|
+
i0.ɵɵelement(0, "mj-empty-state", 11);
|
|
179
|
+
} }
|
|
180
|
+
function UserNotificationsComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
181
|
+
i0.ɵɵelement(0, "mj-empty-state", 12);
|
|
182
|
+
} }
|
|
183
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
184
|
+
i0.ɵɵtext(0);
|
|
185
|
+
} if (rf & 2) {
|
|
186
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
187
|
+
i0.ɵɵtextInterpolate1(" ", vm_r10.Relative, " ");
|
|
188
|
+
} }
|
|
189
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
190
|
+
i0.ɵɵelementStart(0, "time");
|
|
191
|
+
i0.ɵɵtext(1);
|
|
192
|
+
i0.ɵɵpipe(2, "date");
|
|
174
193
|
i0.ɵɵelementEnd();
|
|
175
|
-
|
|
176
|
-
i0.ɵɵ
|
|
194
|
+
} if (rf & 2) {
|
|
195
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
196
|
+
i0.ɵɵattribute("datetime", vm_r10.N.__mj_CreatedAt);
|
|
197
|
+
i0.ɵɵadvance();
|
|
198
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(2, 2, vm_r10.N.__mj_CreatedAt, "MMM d, h:mm a"));
|
|
199
|
+
} }
|
|
200
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
201
|
+
i0.ɵɵelementStart(0, "span", 52);
|
|
202
|
+
i0.ɵɵelement(1, "i", 59);
|
|
203
|
+
i0.ɵɵtext(2, " Open ");
|
|
177
204
|
i0.ɵɵelementEnd();
|
|
178
|
-
i0.ɵɵelementStart(5, "p");
|
|
179
|
-
i0.ɵɵtext(6, "You're all caught up! New notifications will appear here.");
|
|
180
|
-
i0.ɵɵelementEnd()();
|
|
181
205
|
} }
|
|
182
|
-
function
|
|
183
|
-
i0.ɵɵelementStart(0, "
|
|
184
|
-
i0.ɵɵ
|
|
206
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
207
|
+
i0.ɵɵelementStart(0, "p", 53);
|
|
208
|
+
i0.ɵɵtext(1);
|
|
185
209
|
i0.ɵɵelementEnd();
|
|
186
|
-
|
|
187
|
-
i0.ɵɵ
|
|
210
|
+
} if (rf & 2) {
|
|
211
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
212
|
+
i0.ɵɵadvance();
|
|
213
|
+
i0.ɵɵtextInterpolate(vm_r10.Preview);
|
|
214
|
+
} }
|
|
215
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Case_1_Template(rf, ctx) { if (rf & 1) {
|
|
216
|
+
i0.ɵɵelement(0, "div", 61);
|
|
217
|
+
} if (rf & 2) {
|
|
218
|
+
const vm_r10 = i0.ɵɵnextContext(2).$implicit;
|
|
219
|
+
i0.ɵɵproperty("innerHTML", vm_r10.Body, i0.ɵɵsanitizeHtml);
|
|
220
|
+
} }
|
|
221
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Case_2_Template(rf, ctx) { if (rf & 1) {
|
|
222
|
+
i0.ɵɵelement(0, "mj-markdown", 62);
|
|
223
|
+
} if (rf & 2) {
|
|
224
|
+
const vm_r10 = i0.ɵɵnextContext(2).$implicit;
|
|
225
|
+
i0.ɵɵproperty("data", vm_r10.Body)("enableMermaid", false);
|
|
226
|
+
} }
|
|
227
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Case_3_Template(rf, ctx) { if (rf & 1) {
|
|
228
|
+
i0.ɵɵelementStart(0, "p", 63);
|
|
229
|
+
i0.ɵɵtext(1);
|
|
188
230
|
i0.ɵɵelementEnd();
|
|
189
|
-
|
|
190
|
-
i0.ɵɵ
|
|
191
|
-
i0.ɵɵ
|
|
231
|
+
} if (rf & 2) {
|
|
232
|
+
const vm_r10 = i0.ɵɵnextContext(2).$implicit;
|
|
233
|
+
i0.ɵɵadvance();
|
|
234
|
+
i0.ɵɵtextInterpolate(vm_r10.N.Message);
|
|
192
235
|
} }
|
|
193
|
-
function
|
|
236
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
194
237
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
195
|
-
i0.ɵɵelementStart(0, "
|
|
196
|
-
i0.ɵɵlistener("click", function
|
|
197
|
-
i0.ɵɵ
|
|
198
|
-
i0.ɵɵ
|
|
238
|
+
i0.ɵɵelementStart(0, "div", 60);
|
|
239
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
240
|
+
i0.ɵɵconditionalCreate(1, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Case_1_Template, 1, 1, "div", 61)(2, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Case_2_Template, 1, 2, "mj-markdown", 62)(3, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Case_3_Template, 2, 1, "p", 63);
|
|
241
|
+
i0.ɵɵelementEnd();
|
|
242
|
+
} if (rf & 2) {
|
|
243
|
+
let tmp_22_0;
|
|
244
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
245
|
+
i0.ɵɵadvance();
|
|
246
|
+
i0.ɵɵconditional((tmp_22_0 = vm_r10.Kind) === "html" ? 1 : tmp_22_0 === "markdown" ? 2 : 3);
|
|
247
|
+
} }
|
|
248
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
249
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
250
|
+
i0.ɵɵelementStart(0, "button", 64);
|
|
251
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_18_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r12); const vm_r10 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.ToggleExpanded(vm_r10, $event)); });
|
|
252
|
+
i0.ɵɵelement(1, "i", 65);
|
|
253
|
+
i0.ɵɵtext(2);
|
|
254
|
+
i0.ɵɵelementEnd();
|
|
255
|
+
} if (rf & 2) {
|
|
256
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
257
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
258
|
+
i0.ɵɵattribute("aria-expanded", ctx_r0.IsExpanded(vm_r10));
|
|
259
|
+
i0.ɵɵadvance();
|
|
260
|
+
i0.ɵɵclassProp("fa-chevron-down", !ctx_r0.IsExpanded(vm_r10))("fa-chevron-up", ctx_r0.IsExpanded(vm_r10));
|
|
261
|
+
i0.ɵɵadvance();
|
|
262
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.IsExpanded(vm_r10) ? "Show less" : "Show more", " ");
|
|
263
|
+
} }
|
|
264
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
265
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
266
|
+
i0.ɵɵelementStart(0, "button", 66);
|
|
267
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_20_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r13); const vm_r10 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.markAsRead(vm_r10.N, true, null)); });
|
|
268
|
+
i0.ɵɵelement(1, "i", 67);
|
|
269
|
+
i0.ɵɵelementStart(2, "span", 68);
|
|
199
270
|
i0.ɵɵtext(3, "Read");
|
|
200
271
|
i0.ɵɵelementEnd()();
|
|
201
272
|
} if (rf & 2) {
|
|
202
|
-
const
|
|
203
|
-
i0.ɵɵattribute("aria-label", "Mark " +
|
|
273
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
274
|
+
i0.ɵɵattribute("aria-label", "Mark " + vm_r10.N.Title + " as read");
|
|
204
275
|
} }
|
|
205
|
-
function
|
|
206
|
-
const
|
|
207
|
-
i0.ɵɵelementStart(0, "button",
|
|
208
|
-
i0.ɵɵlistener("click", function
|
|
276
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
277
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
278
|
+
i0.ɵɵelementStart(0, "button", 69);
|
|
279
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_21_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const vm_r10 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.markAsRead(vm_r10.N, false, null)); });
|
|
209
280
|
i0.ɵɵelement(1, "i", 20);
|
|
210
|
-
i0.ɵɵelementStart(2, "span",
|
|
281
|
+
i0.ɵɵelementStart(2, "span", 68);
|
|
211
282
|
i0.ɵɵtext(3, "Unread");
|
|
212
283
|
i0.ɵɵelementEnd()();
|
|
213
284
|
} if (rf & 2) {
|
|
214
|
-
const
|
|
215
|
-
i0.ɵɵattribute("aria-label", "Mark " +
|
|
285
|
+
const vm_r10 = i0.ɵɵnextContext().$implicit;
|
|
286
|
+
i0.ɵɵattribute("aria-label", "Mark " + vm_r10.N.Title + " as unread");
|
|
216
287
|
} }
|
|
217
|
-
function
|
|
288
|
+
function UserNotificationsComponent_Conditional_16_For_2_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
218
289
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
219
|
-
i0.ɵɵelementStart(0, "article",
|
|
220
|
-
i0.ɵɵelement(1, "div",
|
|
221
|
-
i0.ɵɵelementStart(2, "div",
|
|
290
|
+
i0.ɵɵelementStart(0, "article", 43);
|
|
291
|
+
i0.ɵɵelement(1, "div", 44);
|
|
292
|
+
i0.ɵɵelementStart(2, "div", 45);
|
|
222
293
|
i0.ɵɵelement(3, "i");
|
|
223
294
|
i0.ɵɵelementEnd();
|
|
224
|
-
i0.ɵɵelementStart(4, "div",
|
|
225
|
-
i0.ɵɵlistener("click", function
|
|
226
|
-
i0.ɵɵelementStart(5, "div",
|
|
295
|
+
i0.ɵɵelementStart(4, "div", 46);
|
|
296
|
+
i0.ɵɵlistener("click", function UserNotificationsComponent_Conditional_16_For_2_For_3_Template_div_click_4_listener() { const vm_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.notificationClicked(vm_r10.N)); });
|
|
297
|
+
i0.ɵɵelementStart(5, "div", 47)(6, "h3", 48);
|
|
227
298
|
i0.ɵɵtext(7);
|
|
228
299
|
i0.ɵɵelementEnd();
|
|
229
|
-
i0.ɵɵelementStart(8, "span",
|
|
230
|
-
i0.ɵɵ
|
|
231
|
-
i0.ɵɵ
|
|
232
|
-
i0.ɵɵtext(11);
|
|
233
|
-
i0.ɵɵpipe(12, "date");
|
|
234
|
-
i0.ɵɵelementEnd()()();
|
|
235
|
-
i0.ɵɵelementStart(13, "div", 56)(14, "span", 57);
|
|
236
|
-
i0.ɵɵtext(15);
|
|
237
|
-
i0.ɵɵelementEnd()();
|
|
238
|
-
i0.ɵɵelementStart(16, "p", 58);
|
|
239
|
-
i0.ɵɵtext(17);
|
|
300
|
+
i0.ɵɵelementStart(8, "span", 49);
|
|
301
|
+
i0.ɵɵpipe(9, "date");
|
|
302
|
+
i0.ɵɵconditionalCreate(10, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_10_Template, 1, 1)(11, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_11_Template, 3, 5, "time");
|
|
240
303
|
i0.ɵɵelementEnd()();
|
|
241
|
-
i0.ɵɵelementStart(
|
|
242
|
-
i0.ɵɵ
|
|
304
|
+
i0.ɵɵelementStart(12, "div", 50)(13, "span", 51);
|
|
305
|
+
i0.ɵɵtext(14);
|
|
306
|
+
i0.ɵɵelementEnd();
|
|
307
|
+
i0.ɵɵconditionalCreate(15, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_15_Template, 3, 0, "span", 52);
|
|
308
|
+
i0.ɵɵelementEnd();
|
|
309
|
+
i0.ɵɵconditionalCreate(16, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_16_Template, 2, 1, "p", 53)(17, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_17_Template, 4, 1, "div", 54);
|
|
310
|
+
i0.ɵɵconditionalCreate(18, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_18_Template, 3, 6, "button", 55);
|
|
311
|
+
i0.ɵɵelementEnd();
|
|
312
|
+
i0.ɵɵelementStart(19, "div", 56);
|
|
313
|
+
i0.ɵɵconditionalCreate(20, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_20_Template, 4, 1, "button", 57)(21, UserNotificationsComponent_Conditional_16_For_2_For_3_Conditional_21_Template, 4, 1, "button", 58);
|
|
243
314
|
i0.ɵɵelementEnd()();
|
|
244
315
|
} if (rf & 2) {
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
i0.ɵɵclassProp("unread",
|
|
248
|
-
i0.ɵɵattribute("aria-label",
|
|
249
|
-
i0.ɵɵadvance(2);
|
|
250
|
-
i0.ɵɵstyleProp("background-color", ctx_r1.getTypeColor(notification_r10) + "15");
|
|
251
|
-
i0.ɵɵadvance();
|
|
252
|
-
i0.ɵɵclassMap("fa-solid " + ctx_r1.getTypeIcon(notification_r10));
|
|
253
|
-
i0.ɵɵstyleProp("color", ctx_r1.getTypeColor(notification_r10));
|
|
316
|
+
const vm_r10 = ctx.$implicit;
|
|
317
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
318
|
+
i0.ɵɵclassProp("unread", vm_r10.N.Unread)("expanded", ctx_r0.IsExpanded(vm_r10))("clickable", vm_r10.Clickable);
|
|
319
|
+
i0.ɵɵattribute("aria-label", vm_r10.N.Title);
|
|
254
320
|
i0.ɵɵadvance(3);
|
|
255
|
-
i0.ɵɵ
|
|
256
|
-
i0.ɵɵ
|
|
257
|
-
i0.ɵɵtextInterpolate1(" ", notification_r10.Title, " ");
|
|
321
|
+
i0.ɵɵclassMap("fa-solid " + ctx_r0.getTypeIcon(vm_r10.N));
|
|
322
|
+
i0.ɵɵstyleProp("color", ctx_r0.getTypeColor(vm_r10.N));
|
|
258
323
|
i0.ɵɵadvance(3);
|
|
259
|
-
i0.ɵɵ
|
|
324
|
+
i0.ɵɵclassProp("card-title-unread", vm_r10.N.Unread);
|
|
260
325
|
i0.ɵɵadvance();
|
|
261
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
262
|
-
i0.ɵɵadvance(3);
|
|
263
|
-
i0.ɵɵstyleProp("background-color", ctx_r1.getTypeColor(notification_r10) + "15")("color", ctx_r1.getTypeColor(notification_r10));
|
|
326
|
+
i0.ɵɵtextInterpolate1(" ", vm_r10.N.Title, " ");
|
|
264
327
|
i0.ɵɵadvance();
|
|
265
|
-
i0.ɵɵ
|
|
328
|
+
i0.ɵɵproperty("title", i0.ɵɵpipeBind2(9, 21, vm_r10.N.__mj_CreatedAt, "medium") ?? "");
|
|
266
329
|
i0.ɵɵadvance(2);
|
|
267
|
-
i0.ɵɵ
|
|
330
|
+
i0.ɵɵconditional(vm_r10.Relative ? 10 : 11);
|
|
331
|
+
i0.ɵɵadvance(4);
|
|
332
|
+
i0.ɵɵtextInterpolate(ctx_r0.getTypeName(vm_r10.N));
|
|
333
|
+
i0.ɵɵadvance();
|
|
334
|
+
i0.ɵɵconditional(vm_r10.Clickable ? 15 : -1);
|
|
335
|
+
i0.ɵɵadvance();
|
|
336
|
+
i0.ɵɵconditional(!ctx_r0.IsExpanded(vm_r10) ? 16 : 17);
|
|
337
|
+
i0.ɵɵadvance(2);
|
|
338
|
+
i0.ɵɵconditional(vm_r10.Expandable ? 18 : -1);
|
|
268
339
|
i0.ɵɵadvance(2);
|
|
269
|
-
i0.ɵɵconditional(
|
|
340
|
+
i0.ɵɵconditional(vm_r10.N.Unread ? 20 : 21);
|
|
341
|
+
} }
|
|
342
|
+
function UserNotificationsComponent_Conditional_16_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
343
|
+
i0.ɵɵelementStart(0, "div", 41);
|
|
344
|
+
i0.ɵɵtext(1);
|
|
345
|
+
i0.ɵɵelementEnd();
|
|
346
|
+
i0.ɵɵrepeaterCreate(2, UserNotificationsComponent_Conditional_16_For_2_For_3_Template, 22, 24, "article", 42, _forTrack2);
|
|
347
|
+
} if (rf & 2) {
|
|
348
|
+
const group_r15 = ctx.$implicit;
|
|
349
|
+
i0.ɵɵadvance();
|
|
350
|
+
i0.ɵɵtextInterpolate(group_r15.Label);
|
|
351
|
+
i0.ɵɵadvance();
|
|
352
|
+
i0.ɵɵrepeater(group_r15.Items);
|
|
270
353
|
} }
|
|
271
|
-
function
|
|
354
|
+
function UserNotificationsComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
272
355
|
i0.ɵɵelementStart(0, "div", 13);
|
|
273
|
-
i0.ɵɵrepeaterCreate(1,
|
|
356
|
+
i0.ɵɵrepeaterCreate(1, UserNotificationsComponent_Conditional_16_For_2_Template, 4, 1, null, null, _forTrack1);
|
|
274
357
|
i0.ɵɵelementEnd();
|
|
275
358
|
} if (rf & 2) {
|
|
276
|
-
const
|
|
359
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
277
360
|
i0.ɵɵadvance();
|
|
278
|
-
i0.ɵɵrepeater(
|
|
361
|
+
i0.ɵɵrepeater(ctx_r0.Groups);
|
|
279
362
|
} }
|
|
363
|
+
/** Collapsed-preview cap (characters of plain text). */
|
|
364
|
+
const PREVIEW_MAX_CHARS = 240;
|
|
365
|
+
/** How often the snapshot relative-time labels refresh. */
|
|
366
|
+
const RELATIVE_REFRESH_MS = 60_000;
|
|
280
367
|
export class UserNotificationsComponent extends BaseAngularComponent {
|
|
281
368
|
sharedService;
|
|
282
369
|
navigationService;
|
|
283
370
|
appManager;
|
|
284
|
-
|
|
285
|
-
unreadRadio;
|
|
286
|
-
readRadio;
|
|
371
|
+
cdr = inject(ChangeDetectorRef);
|
|
287
372
|
radioSelected = 'All';
|
|
288
373
|
currentFilter = '';
|
|
289
374
|
notificationTypes = [];
|
|
290
375
|
selectedTypeFilter = null;
|
|
291
376
|
loadingTypes = true;
|
|
377
|
+
/** IDs of cards currently expanded to their full rendered content. */
|
|
378
|
+
Expanded = new Set();
|
|
379
|
+
groups = [];
|
|
380
|
+
groupsKey = '';
|
|
381
|
+
vmCache = new Map();
|
|
382
|
+
relativeTimer = null;
|
|
292
383
|
constructor(sharedService, navigationService, appManager) {
|
|
293
384
|
super();
|
|
294
385
|
this.sharedService = sharedService;
|
|
@@ -297,10 +388,23 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
297
388
|
}
|
|
298
389
|
async ngOnInit() {
|
|
299
390
|
this.loadNotificationTypes();
|
|
391
|
+
// Refresh the snapshot relative-time labels between change-detection passes.
|
|
392
|
+
this.relativeTimer = setInterval(() => {
|
|
393
|
+
for (const vm of this.vmCache.values()) {
|
|
394
|
+
vm.Relative = this.relativeTime(vm.N.__mj_CreatedAt);
|
|
395
|
+
}
|
|
396
|
+
this.groupsKey = ''; // day buckets can shift at midnight
|
|
397
|
+
this.cdr.markForCheck();
|
|
398
|
+
}, RELATIVE_REFRESH_MS);
|
|
300
399
|
}
|
|
301
400
|
ngAfterViewInit() {
|
|
302
401
|
this.sharedService.InvokeManualResize(); // make sure the notifications component is sized correctly
|
|
303
402
|
}
|
|
403
|
+
ngOnDestroy() {
|
|
404
|
+
if (this.relativeTimer != null) {
|
|
405
|
+
clearInterval(this.relativeTimer);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
304
408
|
loadNotificationTypes() {
|
|
305
409
|
// Get notification types from UserInfoEngine cache, sorted client-side
|
|
306
410
|
// UserInfoEngine is auto-configured via @RegisterForStartup()
|
|
@@ -314,6 +418,9 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
314
418
|
});
|
|
315
419
|
this.loadingTypes = false;
|
|
316
420
|
}
|
|
421
|
+
// ========================================================================
|
|
422
|
+
// Data shaping (filter → view models → day groups)
|
|
423
|
+
// ========================================================================
|
|
317
424
|
get NotificationsToShow() {
|
|
318
425
|
let temp = [];
|
|
319
426
|
switch (this.radioSelected) {
|
|
@@ -339,6 +446,153 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
339
446
|
}
|
|
340
447
|
return temp;
|
|
341
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* The filtered notifications as render-ready day groups. Memoized on a composite
|
|
451
|
+
* key of the inputs so the getter stays cheap across change-detection passes and
|
|
452
|
+
* the (time-sensitive) VM snapshots never rebuild mid-pass.
|
|
453
|
+
*/
|
|
454
|
+
get Groups() {
|
|
455
|
+
const list = this.NotificationsToShow;
|
|
456
|
+
const unread = list.filter(n => n.Unread).length;
|
|
457
|
+
const key = `${list.length}|${unread}|${this.radioSelected}|${this.selectedTypeFilter}|${this.currentFilter}|${list[0]?.ID ?? ''}|${list[list.length - 1]?.ID ?? ''}`;
|
|
458
|
+
if (key !== this.groupsKey) {
|
|
459
|
+
this.groups = this.buildGroups(list);
|
|
460
|
+
this.groupsKey = key;
|
|
461
|
+
}
|
|
462
|
+
return this.groups;
|
|
463
|
+
}
|
|
464
|
+
buildGroups(list) {
|
|
465
|
+
const groups = [];
|
|
466
|
+
let current = null;
|
|
467
|
+
for (const n of list) {
|
|
468
|
+
const label = this.dayLabel(n.__mj_CreatedAt);
|
|
469
|
+
if (!current || current.Label !== label) {
|
|
470
|
+
current = { Key: `${label}-${n.ID}`, Label: label, Items: [] };
|
|
471
|
+
groups.push(current);
|
|
472
|
+
}
|
|
473
|
+
current.Items.push(this.vmFor(n));
|
|
474
|
+
}
|
|
475
|
+
return groups;
|
|
476
|
+
}
|
|
477
|
+
vmFor(n) {
|
|
478
|
+
const cached = this.vmCache.get(n.ID);
|
|
479
|
+
if (cached) {
|
|
480
|
+
cached.N = n;
|
|
481
|
+
cached.Clickable = this.isNotificationClickable(n);
|
|
482
|
+
return cached;
|
|
483
|
+
}
|
|
484
|
+
const { kind, body, preview, expandable } = this.classifyMessage(n.Message ?? '');
|
|
485
|
+
const vm = {
|
|
486
|
+
N: n,
|
|
487
|
+
Kind: kind,
|
|
488
|
+
Body: body,
|
|
489
|
+
Preview: preview,
|
|
490
|
+
Expandable: expandable,
|
|
491
|
+
Relative: this.relativeTime(n.__mj_CreatedAt),
|
|
492
|
+
Clickable: this.isNotificationClickable(n),
|
|
493
|
+
};
|
|
494
|
+
this.vmCache.set(n.ID, vm);
|
|
495
|
+
return vm;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Classifies a notification Message for rendering:
|
|
499
|
+
* - Full HTML documents (e.g. templated email bodies) and HTML fragments →
|
|
500
|
+
* parsed with DOMParser, chrome elements (style/script/link/meta/title) removed,
|
|
501
|
+
* and the body markup kept for a SANITIZED [innerHTML] binding (Angular's
|
|
502
|
+
* default sanitizer strips scripts/event handlers on bind).
|
|
503
|
+
* - Markdown-looking text → rendered through mj-markdown when expanded.
|
|
504
|
+
* - Everything else → plain text.
|
|
505
|
+
*/
|
|
506
|
+
classifyMessage(message) {
|
|
507
|
+
const trimmed = (message ?? '').trim();
|
|
508
|
+
const looksHtml = /^<!doctype\s|^<html[\s>]/i.test(trimmed) || /<\/?[a-z][^>]*>/i.test(trimmed);
|
|
509
|
+
if (looksHtml) {
|
|
510
|
+
const doc = new DOMParser().parseFromString(trimmed, 'text/html');
|
|
511
|
+
for (const el of Array.from(doc.querySelectorAll('style, script, link, meta, title'))) {
|
|
512
|
+
el.remove();
|
|
513
|
+
}
|
|
514
|
+
const body = doc.body?.innerHTML?.trim() ?? '';
|
|
515
|
+
const text = this.collapseWhitespace(doc.body?.textContent ?? '');
|
|
516
|
+
return { kind: 'html', body, preview: this.excerpt(text), expandable: true };
|
|
517
|
+
}
|
|
518
|
+
const looksMarkdown = /(^|\n)#{1,6}\s|\*\*[^*]+\*\*|(^|\n)\s*[-*]\s+|\[[^\]]+\]\([^)]+\)|```/m.test(trimmed);
|
|
519
|
+
const text = this.collapseWhitespace(trimmed);
|
|
520
|
+
if (looksMarkdown) {
|
|
521
|
+
return { kind: 'markdown', body: trimmed, preview: this.excerpt(this.stripMarkdown(text)), expandable: true };
|
|
522
|
+
}
|
|
523
|
+
return { kind: 'text', body: '', preview: text, expandable: text.length > PREVIEW_MAX_CHARS };
|
|
524
|
+
}
|
|
525
|
+
collapseWhitespace(value) {
|
|
526
|
+
return value.replace(/\s+/g, ' ').trim();
|
|
527
|
+
}
|
|
528
|
+
excerpt(text) {
|
|
529
|
+
return text.length > PREVIEW_MAX_CHARS ? `${text.substring(0, PREVIEW_MAX_CHARS - 1)}…` : text;
|
|
530
|
+
}
|
|
531
|
+
/** Light de-noising of markdown syntax for the plain-text preview. */
|
|
532
|
+
stripMarkdown(text) {
|
|
533
|
+
return text
|
|
534
|
+
.replace(/```[\s\S]*?```/g, ' ')
|
|
535
|
+
.replace(/[#*_`>]+/g, '')
|
|
536
|
+
.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
|
|
537
|
+
.replace(/\s+/g, ' ')
|
|
538
|
+
.trim();
|
|
539
|
+
}
|
|
540
|
+
/** Compact "just now / 5m ago / 3h ago / 2d ago" label. NEVER call from templates (NG0100) — snapshot only. */
|
|
541
|
+
relativeTime(value) {
|
|
542
|
+
if (!value) {
|
|
543
|
+
return '';
|
|
544
|
+
}
|
|
545
|
+
const ms = Date.now() - new Date(value).getTime();
|
|
546
|
+
const minutes = Math.floor(ms / 60_000);
|
|
547
|
+
if (minutes < 1)
|
|
548
|
+
return 'just now';
|
|
549
|
+
if (minutes < 60)
|
|
550
|
+
return `${minutes}m ago`;
|
|
551
|
+
const hours = Math.floor(minutes / 60);
|
|
552
|
+
if (hours < 24)
|
|
553
|
+
return `${hours}h ago`;
|
|
554
|
+
const days = Math.floor(hours / 24);
|
|
555
|
+
return days < 7 ? `${days}d ago` : '';
|
|
556
|
+
}
|
|
557
|
+
dayLabel(value) {
|
|
558
|
+
if (!value) {
|
|
559
|
+
return 'Earlier';
|
|
560
|
+
}
|
|
561
|
+
const d = new Date(value);
|
|
562
|
+
const now = new Date();
|
|
563
|
+
const startOfDay = (x) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
|
|
564
|
+
const diffDays = Math.round((startOfDay(now) - startOfDay(d)) / 86_400_000);
|
|
565
|
+
if (diffDays <= 0)
|
|
566
|
+
return 'Today';
|
|
567
|
+
if (diffDays === 1)
|
|
568
|
+
return 'Yesterday';
|
|
569
|
+
if (diffDays < 7)
|
|
570
|
+
return 'This Week';
|
|
571
|
+
return 'Earlier';
|
|
572
|
+
}
|
|
573
|
+
// ========================================================================
|
|
574
|
+
// Expand / collapse
|
|
575
|
+
// ========================================================================
|
|
576
|
+
IsExpanded(vm) {
|
|
577
|
+
return this.Expanded.has(vm.N.ID);
|
|
578
|
+
}
|
|
579
|
+
ToggleExpanded(vm, event) {
|
|
580
|
+
event.stopPropagation();
|
|
581
|
+
if (this.Expanded.has(vm.N.ID)) {
|
|
582
|
+
this.Expanded.delete(vm.N.ID);
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
this.Expanded.add(vm.N.ID);
|
|
586
|
+
// Reading the full content is reading — mark it as such.
|
|
587
|
+
if (vm.N.Unread) {
|
|
588
|
+
void this.markAsRead(vm.N, true, null);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
this.cdr.markForCheck();
|
|
592
|
+
}
|
|
593
|
+
// ========================================================================
|
|
594
|
+
// Clickability + navigation (unchanged behavior)
|
|
595
|
+
// ========================================================================
|
|
342
596
|
isNotificationClickable(notification) {
|
|
343
597
|
// Check for special types navigated via NavigationService (not a URL)
|
|
344
598
|
if (notification.ResourceConfiguration && notification.ResourceConfiguration.trim().length > 0) {
|
|
@@ -416,41 +670,10 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
416
670
|
}
|
|
417
671
|
selectReadOption(option) {
|
|
418
672
|
this.radioSelected = option;
|
|
419
|
-
// now update the radio button group in the UI
|
|
420
|
-
switch (option) {
|
|
421
|
-
case 'All':
|
|
422
|
-
this.allRadio.nativeElement.checked = true;
|
|
423
|
-
break;
|
|
424
|
-
case 'Unread':
|
|
425
|
-
this.unreadRadio.nativeElement.checked = true;
|
|
426
|
-
break;
|
|
427
|
-
case 'Read':
|
|
428
|
-
this.readRadio.nativeElement.checked = true;
|
|
429
|
-
break;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
onReadRadioChanged(event) {
|
|
433
|
-
if (event.target instanceof HTMLInputElement) {
|
|
434
|
-
this.radioSelected = event.target.value;
|
|
435
|
-
}
|
|
436
673
|
}
|
|
437
674
|
onFilterChanged(value) {
|
|
438
675
|
this.currentFilter = value;
|
|
439
676
|
}
|
|
440
|
-
getItemTitleClass(notification) {
|
|
441
|
-
if (notification.Unread) {
|
|
442
|
-
return 'notification-title notification-title-unread';
|
|
443
|
-
}
|
|
444
|
-
return 'notification-title';
|
|
445
|
-
}
|
|
446
|
-
getItemWrapperClass(notification) {
|
|
447
|
-
let classInfo = 'notification-wrap';
|
|
448
|
-
if (this.isNotificationClickable(notification))
|
|
449
|
-
classInfo += ' notification-wrap-clickable';
|
|
450
|
-
if (notification.Unread)
|
|
451
|
-
classInfo += ' notification-wrap-unread';
|
|
452
|
-
return classInfo;
|
|
453
|
-
}
|
|
454
677
|
async markAsRead(notification, bRead, transGroup) {
|
|
455
678
|
if (notification) {
|
|
456
679
|
const notificationId = notification.ID;
|
|
@@ -487,37 +710,6 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
487
710
|
}
|
|
488
711
|
async markAllAsRead() {
|
|
489
712
|
await this.markAll(true);
|
|
490
|
-
// test harness for creating Conversations and Conversation Details record in a single transaction using variables
|
|
491
|
-
await this.TestTransactionGroupVariables();
|
|
492
|
-
}
|
|
493
|
-
async TestTransactionGroupVariables() {
|
|
494
|
-
const md = this.ProviderToUse;
|
|
495
|
-
const transGroup = await md.CreateTransactionGroup();
|
|
496
|
-
const conversation = await md.GetEntityObject('MJ: Conversations');
|
|
497
|
-
conversation.UserID = md.CurrentUser.ID;
|
|
498
|
-
conversation.Description = 'Test Conversation';
|
|
499
|
-
conversation.TransactionGroup = transGroup;
|
|
500
|
-
if (!await conversation.Save()) {
|
|
501
|
-
this.sharedService.CreateSimpleNotification('Unable to create conversation', 'error', 5000);
|
|
502
|
-
}
|
|
503
|
-
const tvDefine = new TransactionVariable('NewConvoID', conversation, 'ID', 'Define');
|
|
504
|
-
transGroup.AddVariable(tvDefine);
|
|
505
|
-
const conversationDetail = await md.GetEntityObject('MJ: Conversation Details');
|
|
506
|
-
conversationDetail.Message = 'Test Message';
|
|
507
|
-
conversationDetail.Role = 'User';
|
|
508
|
-
conversationDetail.ConversationID = 'x'; // fake UUID must be non-null to pass validation, this will be replaced by the variable, since we're part of a TG, not a real save, so doesn't validate it as a true fkey
|
|
509
|
-
conversationDetail.TransactionGroup = transGroup;
|
|
510
|
-
if (!await conversationDetail.Save()) {
|
|
511
|
-
this.sharedService.CreateSimpleNotification('Unable to create conversation detail', 'error', 500);
|
|
512
|
-
}
|
|
513
|
-
const tvUse = new TransactionVariable('NewConvoID', conversationDetail, 'ConversationID', 'Use');
|
|
514
|
-
transGroup.AddVariable(tvUse);
|
|
515
|
-
if (await transGroup.Submit()) {
|
|
516
|
-
this.sharedService.CreateSimpleNotification('Transaction Group with Variables worked', 'success', 5000);
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
this.sharedService.CreateSimpleNotification('Transaction Group with Variables failed', 'error', 5000);
|
|
520
|
-
}
|
|
521
713
|
}
|
|
522
714
|
async markAllAsUnread() {
|
|
523
715
|
await this.markAll(false);
|
|
@@ -684,7 +876,7 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
684
876
|
}
|
|
685
877
|
getTypeColor(notification) {
|
|
686
878
|
const type = this.getNotificationType(notification.NotificationTypeID);
|
|
687
|
-
return type?.Color || '
|
|
879
|
+
return type?.Color || 'var(--mj-text-muted)';
|
|
688
880
|
}
|
|
689
881
|
getTypeName(notification) {
|
|
690
882
|
const type = this.getNotificationType(notification.NotificationTypeID);
|
|
@@ -694,48 +886,36 @@ export class UserNotificationsComponent extends BaseAngularComponent {
|
|
|
694
886
|
this.selectedTypeFilter = typeId;
|
|
695
887
|
}
|
|
696
888
|
static ɵfac = function UserNotificationsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserNotificationsComponent)(i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i1.NavigationService), i0.ɵɵdirectiveInject(i2.ApplicationManager)); };
|
|
697
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserNotificationsComponent, selectors: [["app-user-notifications"]],
|
|
698
|
-
i0.ɵɵ
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
i0.ɵɵ
|
|
702
|
-
i0.ɵɵ
|
|
703
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.readRadio = _t.first);
|
|
704
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 14, vars: 3, consts: [["allRadio", ""], ["unreadRadio", ""], ["readRadio", ""], [1, "notifications-container"], [1, "notifications-header"], [1, "header-top"], [1, "header-title"], [1, "title-icon"], [1, "fa-solid", "fa-bell"], [1, "header-actions"], [1, "filters-section"], [1, "notifications-content"], [1, "empty-state"], [1, "notifications-list"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-double"], [1, "btn-text"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-envelope"], [1, "filters-slider"], [1, "slider-content"], ["role", "group", "aria-label", "Filter notifications by read status", 1, "header-stats"], ["type", "radio", "name", "UnreadStatus", "value", "All", "checked", "", "id", "filter-all", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show all notifications", 1, "stat-pill", 3, "click"], [1, "stat-label"], [1, "stat-count"], ["type", "radio", "name", "UnreadStatus", "value", "Unread", "id", "filter-unread", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "active", "has-unread"], ["type", "radio", "name", "UnreadStatus", "value", "Read", "id", "filter-read", 1, "hidden-radio", 3, "change"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "active"], [1, "filter-item", "type-filter-slider"], [1, "search-section"], [1, "search-container"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass", "search-icon"], ["type", "text", "placeholder", "Search notifications...", "aria-label", "Search notifications", 1, "search-input", 3, "input", "value"], [1, "filter-info"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "click"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "click"], ["aria-label", "Filter by notification type", 1, "type-select", 3, "ngModelChange", "change", "ngModel"], [3, "value"], [1, "filter-badge"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "empty-icon"], [1, "fa-solid", "fa-bell-slash"], [1, "fa-solid", "fa-filter-circle-xmark"], ["role", "article", 1, "notification-card", 3, "unread", "clickable"], ["role", "article", 1, "notification-card"], ["aria-hidden", "true", 1, "card-indicator"], ["aria-hidden", "true", 1, "card-icon"], [1, "card-content", 3, "click"], [1, "card-header"], [1, "card-title"], [1, "card-time"], ["aria-hidden", "true", 1, "fa-regular", "fa-clock"], [1, "card-meta"], [1, "card-type"], [1, "card-message"], [1, "card-actions"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], [1, "action-text"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn", 3, "click"]], template: function UserNotificationsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
705
|
-
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "div", 5)(3, "div", 6)(4, "div", 7);
|
|
706
|
-
i0.ɵɵelement(5, "i", 8);
|
|
889
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserNotificationsComponent, selectors: [["app-user-notifications"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 17, vars: 4, consts: [[1, "notifications-container"], [1, "notifications-header"], [1, "header-top"], [1, "header-title"], [1, "title-icon"], [1, "fa-solid", "fa-bell"], [1, "title-text"], [1, "title-subtitle"], [1, "header-actions"], [1, "filters-section"], [1, "notifications-content"], ["Variant", "success", "Icon", "fa-solid fa-bell-slash", "Title", "No Notifications", "Message", "You're all caught up! New notifications will appear here."], ["Variant", "no-results", "Icon", "fa-solid fa-filter-circle-xmark", "Title", "No Matching Notifications", "Message", "Try adjusting your filters to see more notifications."], [1, "notifications-list"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary"], ["type", "button", "aria-label", "Mark all notifications as read", 1, "action-btn", "action-btn-ghost", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-double"], [1, "btn-text"], ["type", "button", "aria-label", "Mark all notifications as unread", 1, "action-btn", "action-btn-secondary", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-envelope"], [1, "filters-slider"], [1, "slider-content"], ["role", "group", "aria-label", "Filter notifications by read status", 1, "header-stats"], ["type", "button", "aria-label", "Show all notifications", 1, "stat-pill", 3, "click"], [1, "stat-label"], [1, "stat-count"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "active", "has-unread"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "active"], [1, "filter-item", "type-filter-slider"], [1, "search-section"], [1, "search-container"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass", "search-icon"], ["type", "text", "placeholder", "Search notifications...", "aria-label", "Search notifications", 1, "search-input", 3, "input", "value"], [1, "filter-info"], ["type", "button", "aria-label", "Show unread notifications", 1, "stat-pill", 3, "click"], ["type", "button", "aria-label", "Show read notifications", 1, "stat-pill", 3, "click"], ["aria-label", "Filter by notification type", 1, "type-select", 3, "ngModelChange", "change", "ngModel"], [3, "value"], [1, "filter-badge"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "group-label"], ["role", "article", 1, "notification-card", 3, "unread", "expanded", "clickable"], ["role", "article", 1, "notification-card"], ["aria-hidden", "true", 1, "card-indicator"], ["aria-hidden", "true", 1, "card-icon"], [1, "card-content", 3, "click"], [1, "card-header"], [1, "card-title"], [1, "card-time", 3, "title"], [1, "card-meta"], [1, "card-type"], [1, "card-open-hint"], [1, "card-message"], [1, "card-rich"], ["type", "button", 1, "card-expand-btn"], [1, "card-actions"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "card-rich", 3, "click"], [1, "card-rich-html", 3, "innerHTML"], [1, "card-rich-md", 3, "data", "enableMermaid"], [1, "card-message", "card-message-full"], ["type", "button", 1, "card-expand-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid"], ["type", "button", "title", "Mark as Read", 1, "card-action-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], [1, "action-text"], ["type", "button", "title", "Mark as Unread", 1, "card-action-btn", 3, "click"]], template: function UserNotificationsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
890
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3)(4, "div", 4);
|
|
891
|
+
i0.ɵɵelement(5, "i", 5);
|
|
892
|
+
i0.ɵɵelementEnd();
|
|
893
|
+
i0.ɵɵelementStart(6, "div", 6)(7, "h1");
|
|
894
|
+
i0.ɵɵtext(8, "Notifications");
|
|
707
895
|
i0.ɵɵelementEnd();
|
|
708
|
-
i0.ɵɵ
|
|
709
|
-
i0.ɵɵtext(7, "Notifications");
|
|
896
|
+
i0.ɵɵconditionalCreate(9, UserNotificationsComponent_Conditional_9_Template, 2, 1, "span", 7)(10, UserNotificationsComponent_Conditional_10_Template, 2, 0, "span", 7);
|
|
710
897
|
i0.ɵɵelementEnd()();
|
|
711
|
-
i0.ɵɵconditionalCreate(
|
|
898
|
+
i0.ɵɵconditionalCreate(11, UserNotificationsComponent_Conditional_11_Template, 3, 2, "div", 8);
|
|
712
899
|
i0.ɵɵelementEnd();
|
|
713
|
-
i0.ɵɵconditionalCreate(
|
|
900
|
+
i0.ɵɵconditionalCreate(12, UserNotificationsComponent_Conditional_12_Template, 17, 9, "div", 9);
|
|
714
901
|
i0.ɵɵelementEnd();
|
|
715
|
-
i0.ɵɵelementStart(
|
|
716
|
-
i0.ɵɵconditionalCreate(
|
|
902
|
+
i0.ɵɵelementStart(13, "div", 10);
|
|
903
|
+
i0.ɵɵconditionalCreate(14, UserNotificationsComponent_Conditional_14_Template, 1, 0, "mj-empty-state", 11)(15, UserNotificationsComponent_Conditional_15_Template, 1, 0, "mj-empty-state", 12)(16, UserNotificationsComponent_Conditional_16_Template, 3, 0, "div", 13);
|
|
717
904
|
i0.ɵɵelementEnd()();
|
|
718
905
|
} if (rf & 2) {
|
|
719
|
-
i0.ɵɵadvance(
|
|
720
|
-
i0.ɵɵconditional(ctx.AllNotifications.length > 0 ?
|
|
906
|
+
i0.ɵɵadvance(9);
|
|
907
|
+
i0.ɵɵconditional(ctx.UnreadNotifications.length > 0 ? 9 : ctx.AllNotifications.length > 0 ? 10 : -1);
|
|
908
|
+
i0.ɵɵadvance(2);
|
|
909
|
+
i0.ɵɵconditional(ctx.AllNotifications.length > 0 ? 11 : -1);
|
|
721
910
|
i0.ɵɵadvance();
|
|
722
|
-
i0.ɵɵconditional(ctx.AllNotifications.length > 0 ?
|
|
911
|
+
i0.ɵɵconditional(ctx.AllNotifications.length > 0 ? 12 : -1);
|
|
723
912
|
i0.ɵɵadvance(2);
|
|
724
|
-
i0.ɵɵconditional(ctx.NotificationsToShow.length === 0 && ctx.AllNotifications.length === 0 ?
|
|
725
|
-
} }, dependencies: [i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.DatePipe], styles: ["\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n\n\n\n\n\n.notifications-container[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n}\n\n\n\n\n\n\n.notifications-header[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0;\n flex-shrink: 0;\n}\n\n\n\n.header-top[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 24px 24px 16px;\n gap: 16px;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.title-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n background: var(--mj-brand-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.title-icon[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n.title-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 22px;\n color: white;\n}\n\n.header-title[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n letter-spacing: -0.02em;\n}\n\n\n\n\n\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border-radius: 9999px; \n\n font-size: 14px;\n font-weight: 600;\n border: 2px solid var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n font-family: inherit;\n}\n\n.action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n transition: transform 0.2s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n\n\n.action-btn-ghost[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.action-btn-ghost[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md);\n}\n\n.action-btn-ghost[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n\n\n.action-btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.action-btn-secondary[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n}\n\n.action-btn-secondary[_ngcontent-%COMP%]:active {\n transform: scale(0.98);\n}\n\n\n\n\n\n\n.filters-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\n}\n\n.filters-slider[_ngcontent-%COMP%] {\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.filters-slider[_ngcontent-%COMP%]::-webkit-scrollbar {\n display: none;\n}\n\n.slider-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n min-width: min-content;\n}\n\n\n\n\n\n\n.header-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-shrink: 0;\n}\n\n.hidden-radio[_ngcontent-%COMP%] {\n position: absolute;\n opacity: 0;\n pointer-events: none;\n}\n\n.stat-pill[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border-radius: 9999px; \n\n border: 2px solid var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n min-height: 44px;\n}\n\n.stat-pill[_ngcontent-%COMP%]:hover:not(.active) {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n}\n\n\n\n.stat-pill.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: white;\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n transform: translateY(-1px);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n}\n\n.stat-count[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 700;\n padding: 4px 10px;\n border-radius: 9999px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n min-width: 28px;\n text-align: center;\n transition: all 0.2s ease;\n}\n\n.stat-pill.active[_ngcontent-%COMP%] .stat-count[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.25);\n color: white;\n}\n\n.stat-count.unread-count[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 700;\n}\n\n.stat-pill.has-unread[_ngcontent-%COMP%]:not(.active) {\n border-color: var(--mj-brand-primary);\n}\n\n\n\n\n\n\n.type-filter-slider[_ngcontent-%COMP%] {\n flex-shrink: 0;\n min-width: 180px;\n}\n\n\n\n\n\n\n.search-section[_ngcontent-%COMP%] {\n padding: 0 24px 16px;\n}\n\n\n\n\n\n\n.filter-info[_ngcontent-%COMP%] {\n padding: 0 24px 16px;\n display: flex;\n justify-content: center;\n}\n\n\n\n.type-select[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 16px;\n border: 2px solid var(--mj-brand-primary);\n border-radius: 9999px; \n\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%230076B6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 16px center;\n padding-right: 42px;\n}\n\n.type-select[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background-color: var(--mj-bg-surface-card);\n}\n\n.type-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-container[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n max-width: 100%;\n}\n\n.search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 16px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary);\n font-size: 14px;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n.search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 16px 10px 44px;\n border: 2px solid var(--mj-brand-primary);\n border-radius: 9999px; \n\n font-size: 14px;\n font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n}\n\n.search-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.search-input[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-card);\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n background: var(--mj-bg-surface);\n}\n\n.search-container[_ngcontent-%COMP%]:focus-within .search-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 9999px; \n\n font-size: 13px;\n font-weight: 600;\n border: 1px solid var(--mj-brand-primary);\n}\n\n.filter-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n\n\n\n.notifications-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch; \n\n}\n\n\n\n.notifications-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.notifications-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-card);\n}\n\n.notifications-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: var(--mj-border-default);\n border-radius: 4px;\n}\n\n.notifications-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-muted);\n}\n\n\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: 80px 32px;\n text-align: center;\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n width: 96px;\n height: 96px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 50%;\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: 40px;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 15px;\n color: var(--mj-text-secondary);\n margin: 0;\n max-width: 320px;\n line-height: 1.5;\n}\n\n\n\n\n\n\n.notifications-list[_ngcontent-%COMP%] {\n background: transparent;\n}\n\n\n\n\n\n\n.notification-card[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 4px 56px 1fr auto;\n gap: 14px;\n align-items: start;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n}\n\n.notification-card[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.notification-card[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.notification-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.notification-card.clickable[_ngcontent-%COMP%]:active {\n background: var(--mj-bg-surface-sunken);\n transform: scale(0.995);\n}\n\n\n\n.notification-card.unread[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.notification-card.unread[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-card));\n}\n\n\n\n.card-indicator[_ngcontent-%COMP%] {\n width: 4px;\n height: 100%;\n min-height: 64px;\n border-radius: 2px;\n background: transparent;\n transition: all 0.2s ease;\n align-self: stretch;\n}\n\n.notification-card.unread[_ngcontent-%COMP%] .card-indicator[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n\n\n.card-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s ease;\n}\n\n.notification-card[_ngcontent-%COMP%]:hover .card-icon[_ngcontent-%COMP%] {\n transform: scale(1.05);\n}\n\n.card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n}\n\n\n\n.card-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 6px;\n}\n\n.card-title[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin: 0;\n line-height: 1.4;\n word-wrap: break-word;\n}\n\n.card-title-unread[_ngcontent-%COMP%] {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.notification-card.clickable[_ngcontent-%COMP%] .card-title[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.notification-card.clickable[_ngcontent-%COMP%]:hover .card-title[_ngcontent-%COMP%] {\n text-decoration: underline;\n}\n\n.card-time[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.card-time[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.card-meta[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n}\n\n.card-type[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 4px 12px;\n border-radius: 9999px; \n\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n\n\n.card-message[_ngcontent-%COMP%] {\n font-size: 15px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n\n\n.card-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding-top: 6px;\n}\n\n.card-action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border-radius: 9999px; \n\n font-size: 13px;\n font-weight: 600;\n border: 2px solid var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n font-family: inherit;\n}\n\n.card-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: white;\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.card-action-btn[_ngcontent-%COMP%]:active {\n transform: translateY(0) scale(0.98);\n}\n\n.card-action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_slideInUp {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.notification-card[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_slideInUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n\n\n\n\n\nbutton[_ngcontent-%COMP%]:focus-visible, \ninput[_ngcontent-%COMP%]:focus-visible, \nselect[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n\n\n\n\n\n\n\n@media (max-width: 768px) {\n .notifications-container[_ngcontent-%COMP%] {\n border-radius: 0;\n box-shadow: none;\n }\n\n .header-top[_ngcontent-%COMP%] {\n padding: 20px 20px 14px;\n }\n\n .title-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n }\n\n .title-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .header-title[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n }\n\n \n\n .slider-content[_ngcontent-%COMP%] {\n padding: 14px 20px;\n gap: 10px;\n }\n\n .stat-pill[_ngcontent-%COMP%] {\n padding: 8px 16px;\n flex-shrink: 0;\n }\n\n .type-filter-slider[_ngcontent-%COMP%] {\n min-width: 160px;\n }\n\n .search-section[_ngcontent-%COMP%] {\n padding: 0 20px 14px;\n }\n\n .filter-info[_ngcontent-%COMP%] {\n padding: 0 20px 14px;\n }\n\n .notification-card[_ngcontent-%COMP%] {\n grid-template-columns: 4px 52px 1fr;\n gap: 12px;\n padding: 14px 16px;\n }\n\n .card-actions[_ngcontent-%COMP%] {\n grid-column: 2 / -1;\n padding-top: 10px;\n }\n\n .card-icon[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n }\n\n .card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 22px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .header-top[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n gap: 12px;\n padding: 16px 16px 12px;\n }\n\n .header-title[_ngcontent-%COMP%] {\n justify-content: flex-start;\n }\n\n .title-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n }\n\n .title-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .header-title[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n font-size: 1.375rem;\n }\n\n .header-actions[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: stretch;\n gap: 8px;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n flex: 1;\n justify-content: center;\n padding: 10px 16px;\n font-size: 13px;\n }\n\n .btn-text[_ngcontent-%COMP%] {\n display: none;\n }\n\n \n\n .slider-content[_ngcontent-%COMP%] {\n padding: 12px 16px;\n gap: 8px;\n }\n\n .header-stats[_ngcontent-%COMP%] {\n gap: 8px;\n }\n\n .stat-pill[_ngcontent-%COMP%] {\n padding: 8px 14px;\n min-height: 40px;\n flex-shrink: 0;\n }\n\n .stat-label[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .stat-count[_ngcontent-%COMP%] {\n font-size: 12px;\n padding: 3px 8px;\n min-width: 24px;\n }\n\n .type-filter-slider[_ngcontent-%COMP%] {\n min-width: 140px;\n }\n\n .type-select[_ngcontent-%COMP%], \n .search-input[_ngcontent-%COMP%] {\n font-size: 16px; \n\n }\n\n .search-section[_ngcontent-%COMP%] {\n padding: 0 16px 12px;\n }\n\n .filter-info[_ngcontent-%COMP%] {\n padding: 0 16px 12px;\n }\n\n .notification-card[_ngcontent-%COMP%] {\n grid-template-columns: 3px 48px 1fr;\n gap: 10px;\n padding: 12px 12px;\n }\n\n .card-indicator[_ngcontent-%COMP%] {\n width: 3px;\n min-height: 56px;\n }\n\n .card-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n }\n\n .card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 20px;\n }\n\n .card-title[_ngcontent-%COMP%] {\n font-size: 15px;\n }\n\n .card-time[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .card-message[_ngcontent-%COMP%] {\n font-size: 14px;\n -webkit-line-clamp: 2;\n }\n\n .card-type[_ngcontent-%COMP%] {\n font-size: 11px;\n padding: 3px 10px;\n }\n\n .card-actions[_ngcontent-%COMP%] {\n padding-top: 8px;\n gap: 6px;\n }\n\n .action-text[_ngcontent-%COMP%] {\n display: none;\n }\n\n .card-action-btn[_ngcontent-%COMP%] {\n padding: 8px 12px;\n min-width: 40px;\n justify-content: center;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 60px 20px;\n }\n\n .empty-icon[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n }\n\n .empty-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n }\n\n .empty-state[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n}\n\n\n\n@media (min-width: 390px) and (max-width: 480px) {\n .btn-text[_ngcontent-%COMP%] {\n display: inline;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n font-size: 14px;\n }\n}\n\n\n\n@media (prefers-color-scheme: dark) {\n \n\n}"] });
|
|
913
|
+
i0.ɵɵconditional(ctx.NotificationsToShow.length === 0 && ctx.AllNotifications.length === 0 ? 14 : ctx.NotificationsToShow.length === 0 ? 15 : 16);
|
|
914
|
+
} }, dependencies: [i3.MarkdownComponent, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.SelectControlValueAccessor, i4.NgControlStatus, i4.NgModel, i5.MJEmptyStateComponent, i6.DatePipe], styles: ["\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.notifications-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n}\n\n\n\n\n.notifications-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n padding: 20px 24px 12px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.header-top[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 14px;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.title-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: var(--mj-radius-lg, 12px);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.title-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.title-text[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.title-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 12px;\n border-radius: var(--mj-radius-md, 8px);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.15s, color 0.15s, border-color 0.15s;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.action-btn-ghost[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.action-btn-ghost[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n\n.filters-section[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n}\n\n.filters-slider[_ngcontent-%COMP%] {\n min-width: 0;\n}\n\n.slider-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.header-stats[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: 4px;\n padding: 3px;\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-bg-surface-sunken);\n}\n\n.stat-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border: none;\n border-radius: var(--mj-radius-full, 999px);\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.15s, color 0.15s;\n}\n\n.stat-pill[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.stat-pill.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.stat-count[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--mj-radius-full, 999px);\n background: color-mix(in srgb, var(--mj-text-muted) 14%, transparent);\n color: var(--mj-text-secondary);\n font-size: 10px;\n font-weight: 700;\n}\n\n.stat-count.unread-count[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.type-select[_ngcontent-%COMP%] {\n padding: 7px 10px;\n border-radius: var(--mj-radius-md, 8px);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.search-section[_ngcontent-%COMP%] {\n flex: 1 1 220px;\n min-width: 180px;\n}\n\n.search-container[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 12px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n}\n\n.search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 8px 12px 8px 32px;\n border-radius: var(--mj-radius-md, 8px);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.filter-info[_ngcontent-%COMP%] {\n flex-basis: 100%;\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: var(--mj-radius-full, 999px);\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n font-size: 11px;\n font-weight: 600;\n}\n\n\n\n\n.notifications-content[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n overflow-y: auto;\n padding: 16px 24px 32px 24px;\n}\n\n.notifications-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n max-width: 960px;\n margin: 0 auto;\n}\n\n.group-label[_ngcontent-%COMP%] {\n position: sticky;\n top: -16px;\n z-index: 1;\n padding: 10px 2px 4px 2px;\n background: var(--mj-bg-page);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--mj-text-muted);\n}\n\n.group-label[_ngcontent-%COMP%]:not(:first-child) {\n margin-top: 8px;\n}\n\n\n\n\n.notification-card[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 12px);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s, box-shadow 0.15s, background-color 0.15s;\n overflow: hidden;\n}\n\n.notification-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.notification-card.unread[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, var(--mj-bg-surface));\n}\n\n.card-indicator[_ngcontent-%COMP%] {\n display: none;\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background: var(--mj-brand-primary);\n border-radius: 0 2px 2px 0;\n}\n\n.notification-card.unread[_ngcontent-%COMP%] .card-indicator[_ngcontent-%COMP%] {\n display: block;\n}\n\n.card-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md, 10px);\n background: var(--mj-bg-surface-sunken);\n font-size: 14px;\n}\n\n.card-content[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.notification-card.clickable[_ngcontent-%COMP%] .card-content[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n}\n\n.card-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow-wrap: anywhere;\n}\n\n.card-title-unread[_ngcontent-%COMP%] {\n font-weight: 700;\n}\n\n.card-time[_ngcontent-%COMP%] {\n flex-shrink: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.card-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 3px 0 6px 0;\n}\n\n.card-type[_ngcontent-%COMP%] {\n display: inline-flex;\n padding: 2px 8px;\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.card-open-hint[_ngcontent-%COMP%] {\n display: none;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.notification-card.clickable[_ngcontent-%COMP%]:hover .card-open-hint[_ngcontent-%COMP%] {\n display: inline-flex;\n}\n\n.card-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--mj-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n\n.card-message-full[_ngcontent-%COMP%] {\n display: block;\n -webkit-line-clamp: unset;\n white-space: pre-wrap;\n}\n\n\n\n\n.card-rich[_ngcontent-%COMP%] {\n margin-top: 4px;\n padding: 12px 14px;\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n cursor: default;\n}\n\n\n\n.card-rich-html[_ngcontent-%COMP%] {\n font-size: 13px;\n line-height: 1.55;\n color: var(--mj-text-primary);\n overflow-x: auto;\n}\n\n.card-rich-html[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n max-width: 100%;\n height: auto;\n}\n\n.card-rich-html[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n max-width: 100%;\n border-collapse: collapse;\n}\n\n.card-rich-html[_ngcontent-%COMP%] td[_ngcontent-%COMP%], \n.card-rich-html[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 4px 8px;\n border: 1px solid var(--mj-border-subtle);\n}\n\n.card-rich-html[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--mj-text-link);\n}\n\n.card-rich-html[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], \n.card-rich-html[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], \n.card-rich-html[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0.4em 0 0.3em 0;\n font-size: 1.05em;\n}\n\n.card-rich-md[_ngcontent-%COMP%] {\n display: block;\n font-size: 13px;\n}\n\n.card-expand-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n padding: 4px 10px;\n border: none;\n border-radius: var(--mj-radius-full, 999px);\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 11px;\n font-weight: 700;\n cursor: pointer;\n}\n\n.card-expand-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n\n\n\n.card-actions[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: flex;\n align-items: flex-start;\n}\n\n.card-action-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n border: 1px solid transparent;\n border-radius: var(--mj-radius-md, 8px);\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.15s, color 0.15s;\n}\n\n.card-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-default);\n}\n\n\n\n\n@media (max-width: 720px) {\n .notifications-header[_ngcontent-%COMP%] {\n padding: 14px 14px 10px 14px;\n }\n\n .notifications-content[_ngcontent-%COMP%] {\n padding: 12px 12px 24px 12px;\n }\n\n .btn-text[_ngcontent-%COMP%], \n .action-text[_ngcontent-%COMP%] {\n display: none;\n }\n\n .card-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 2px;\n }\n\n .card-time[_ngcontent-%COMP%] {\n order: -1;\n }\n}"] });
|
|
726
915
|
}
|
|
727
916
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserNotificationsComponent, [{
|
|
728
917
|
type: Component,
|
|
729
|
-
args: [{ standalone: false, selector: 'app-user-notifications', template: "<div class=\"notifications-container\">\n <!-- Header Section -->\n <div class=\"notifications-header\">\n <div class=\"header-top\">\n <div class=\"header-title\">\n <div class=\"title-icon\">\n <i class=\"fa-solid fa-bell\"></i>\n </div>\n <h1>Notifications</h1>\n </div>\n\n @if (AllNotifications.length > 0) {\n <div class=\"header-actions\">\n @if (UnreadNotifications.length > 0) {\n <button class=\"action-btn action-btn-ghost\"\n type=\"button\"\n (click)=\"markAllAsRead()\"\n aria-label=\"Mark all notifications as read\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Read</span>\n </button>\n }\n @if (ReadNotifications.length > 0) {\n <button class=\"action-btn action-btn-secondary\"\n type=\"button\"\n (click)=\"markAllAsUnread()\"\n aria-label=\"Mark all notifications as unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Unread</span>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Filters Section -->\n @if (AllNotifications.length > 0) {\n <div class=\"filters-section\">\n <!-- Horizontal Slider for Filters (Mobile) -->\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Stats Pills (Filter Tabs) -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <input #allRadio type=\"radio\" name=\"UnreadStatus\" value=\"All\"\n (change)=\"onReadRadioChanged($event)\" checked class=\"hidden-radio\"\n id=\"filter-all\" />\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'All'\"\n (click)=\"selectReadOption('All')\"\n [attr.aria-pressed]=\"radioSelected === 'All'\"\n aria-label=\"Show all notifications\">\n <span class=\"stat-label\">All</span>\n <span class=\"stat-count\">{{AllNotifications.length}}</span>\n </button>\n\n <input #unreadRadio type=\"radio\" name=\"UnreadStatus\" value=\"Unread\"\n (change)=\"onReadRadioChanged($event)\" class=\"hidden-radio\"\n id=\"filter-unread\" />\n @if (UnreadNotifications.length > 0 || ReadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Unread'\"\n [class.has-unread]=\"UnreadNotifications.length > 0\"\n (click)=\"selectReadOption('Unread')\"\n [attr.aria-pressed]=\"radioSelected === 'Unread'\"\n aria-label=\"Show unread notifications\">\n <span class=\"stat-label\">Unread</span>\n <span class=\"stat-count\" [class.unread-count]=\"UnreadNotifications.length > 0\">\n {{UnreadNotifications.length}}\n </span>\n </button>\n }\n\n <input #readRadio type=\"radio\" name=\"UnreadStatus\" value=\"Read\"\n (change)=\"onReadRadioChanged($event)\" class=\"hidden-radio\"\n id=\"filter-read\" />\n @if (ReadNotifications.length > 0 || UnreadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Read'\"\n (click)=\"selectReadOption('Read')\"\n [attr.aria-pressed]=\"radioSelected === 'Read'\"\n aria-label=\"Show read notifications\">\n <span class=\"stat-label\">Read</span>\n <span class=\"stat-count\">{{ReadNotifications.length}}</span>\n </button>\n }\n </div>\n\n <!-- Native Type Filter Dropdown (in slider on mobile) -->\n @if (notificationTypes.length > 0) {\n <div class=\"filter-item type-filter-slider\">\n <select class=\"type-select\"\n [(ngModel)]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange(selectedTypeFilter)\"\n aria-label=\"Filter by notification type\">\n <option [value]=\"null\">All Types</option>\n @for (type of notificationTypes; track type.ID) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n </div>\n }\n </div>\n </div>\n\n <!-- Search Filter (separate, full-width on mobile) -->\n <div class=\"search-section\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search notifications...\"\n [value]=\"currentFilter\"\n (input)=\"onFilterChanged($any($event.target).value)\"\n aria-label=\"Search notifications\" />\n </div>\n </div>\n\n <!-- Filter Info Badge -->\n @if (NotificationsToShow.length !== AllNotifications.length) {\n <div class=\"filter-info\">\n <span class=\"filter-badge\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Showing {{NotificationsToShow.length}} of {{AllNotifications.length}}\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Notifications Content -->\n <div class=\"notifications-content\">\n @if (NotificationsToShow.length === 0 && AllNotifications.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n </div>\n <h3>No Notifications</h3>\n <p>You're all caught up! New notifications will appear here.</p>\n </div>\n } @else if (NotificationsToShow.length === 0) {\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <i class=\"fa-solid fa-filter-circle-xmark\"></i>\n </div>\n <h3>No Matching Notifications</h3>\n <p>Try adjusting your filters to see more notifications.</p>\n </div>\n } @else {\n <!-- Notifications List -->\n <div class=\"notifications-list\">\n @for (notification of NotificationsToShow; track notification.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"notification.Unread\"\n [class.clickable]=\"isNotificationClickable(notification)\"\n role=\"article\"\n [attr.aria-label]=\"notification.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\"\n [style.background-color]=\"getTypeColor(notification) + '15'\"\n aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(notification)\"\n [style.color]=\"getTypeColor(notification)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(notification)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"notification.Unread\">\n {{notification.Title}}\n </h3>\n <span class=\"card-time\">\n <i class=\"fa-regular fa-clock\" aria-hidden=\"true\"></i>\n <time [attr.datetime]=\"notification.__mj_CreatedAt\">\n {{notification.__mj_CreatedAt | date:'MMM d, h:mm a'}}\n </time>\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\"\n [style.background-color]=\"getTypeColor(notification) + '15'\"\n [style.color]=\"getTypeColor(notification)\">\n {{getTypeName(notification)}}\n </span>\n </div>\n\n <p class=\"card-message\">{{notification.Message}}</p>\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (notification.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(notification, true, null)\"\n [attr.aria-label]=\"'Mark ' + notification.Title + ' as read'\"\n title=\"Mark as Read\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Read</span>\n </button>\n } @else {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(notification, false, null)\"\n [attr.aria-label]=\"'Mark ' + notification.Title + ' as unread'\"\n title=\"Mark as Unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Unread</span>\n </button>\n }\n </div>\n </article>\n }\n </div>\n }\n </div>\n</div>\n", styles: ["/* ===================================\n USER NOTIFICATIONS - MD3 DESIGN\n iPhone-inspired UX with Circular Buttons\n =================================== */\n\n:host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n/* ===================================\n CONTAINER\n =================================== */\n\n.notifications-container {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n}\n\n/* ===================================\n HEADER SECTION\n =================================== */\n\n.notifications-header {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0;\n flex-shrink: 0;\n}\n\n/* Header Top Row */\n.header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 24px 24px 16px;\n gap: 16px;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.title-icon {\n width: 48px;\n height: 48px;\n background: var(--mj-brand-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.title-icon:hover {\n transform: scale(1.05);\n}\n\n.title-icon i {\n font-size: 22px;\n color: white;\n}\n\n.header-title h1 {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n letter-spacing: -0.02em;\n}\n\n/* ===================================\n HEADER ACTIONS - Circular Buttons\n =================================== */\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.action-btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border-radius: 9999px; /* Circular design */\n font-size: 14px;\n font-weight: 600;\n border: 2px solid var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n font-family: inherit;\n}\n\n.action-btn i {\n font-size: 16px;\n transition: transform 0.2s ease;\n}\n\n.action-btn:hover i {\n transform: scale(1.1);\n}\n\n/* Ghost Button - White Background (Mark All Read) */\n.action-btn-ghost {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.action-btn-ghost:hover {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-md);\n}\n\n.action-btn-ghost:active {\n background: var(--mj-brand-primary);\n transform: scale(0.98);\n}\n\n/* Secondary Button */\n.action-btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.action-btn-secondary:hover {\n background: var(--mj-brand-primary);\n color: white;\n border-color: var(--mj-brand-primary);\n}\n\n.action-btn-secondary:active {\n transform: scale(0.98);\n}\n\n/* ===================================\n FILTERS SECTION\n =================================== */\n\n.filters-section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n background: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\n}\n\n.filters-slider {\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.filters-slider::-webkit-scrollbar {\n display: none;\n}\n\n.slider-content {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 24px;\n min-width: min-content;\n}\n\n/* ===================================\n STATS PILLS (Filter Tabs) - Circular with mj-blue Active\n =================================== */\n\n.header-stats {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-shrink: 0;\n}\n\n.hidden-radio {\n position: absolute;\n opacity: 0;\n pointer-events: none;\n}\n\n.stat-pill {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border-radius: 9999px; /* Circular design */\n border: 2px solid var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n min-height: 44px;\n}\n\n.stat-pill:hover:not(.active) {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n}\n\n/* Active State - MJ Blue */\n.stat-pill.active {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: white;\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n transform: translateY(-1px);\n}\n\n.stat-label {\n font-size: 14px;\n font-weight: 600;\n}\n\n.stat-count {\n font-size: 13px;\n font-weight: 700;\n padding: 4px 10px;\n border-radius: 9999px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n min-width: 28px;\n text-align: center;\n transition: all 0.2s ease;\n}\n\n.stat-pill.active .stat-count {\n background: rgba(255, 255, 255, 0.25);\n color: white;\n}\n\n.stat-count.unread-count {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-weight: 700;\n}\n\n.stat-pill.has-unread:not(.active) {\n border-color: var(--mj-brand-primary);\n}\n\n/* ===================================\n TYPE FILTER IN SLIDER\n =================================== */\n\n.type-filter-slider {\n flex-shrink: 0;\n min-width: 180px;\n}\n\n/* ===================================\n SEARCH SECTION\n =================================== */\n\n.search-section {\n padding: 0 24px 16px;\n}\n\n/* ===================================\n FILTER INFO\n =================================== */\n\n.filter-info {\n padding: 0 24px 16px;\n display: flex;\n justify-content: center;\n}\n\n/* Native Select Dropdown Styling */\n.type-select {\n width: 100%;\n padding: 10px 16px;\n border: 2px solid var(--mj-brand-primary);\n border-radius: 9999px; /* Circular design */\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%230076B6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 16px center;\n padding-right: 42px;\n}\n\n.type-select:hover {\n border-color: var(--mj-brand-primary);\n background-color: var(--mj-bg-surface-card);\n}\n\n.type-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-container {\n position: relative;\n width: 100%;\n max-width: 100%;\n}\n\n.search-icon {\n position: absolute;\n left: 16px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-secondary);\n font-size: 14px;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n.search-input {\n width: 100%;\n padding: 10px 16px 10px 44px;\n border: 2px solid var(--mj-brand-primary);\n border-radius: 9999px; /* Circular design */\n font-size: 14px;\n font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n font-family: inherit;\n}\n\n.search-input::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.search-input:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-card);\n}\n\n.search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n background: var(--mj-bg-surface);\n}\n\n.search-container:focus-within .search-icon {\n color: var(--mj-brand-primary);\n}\n\n.filter-badge {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 14px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 9999px; /* Circular design */\n font-size: 13px;\n font-weight: 600;\n border: 1px solid var(--mj-brand-primary);\n}\n\n.filter-badge i {\n font-size: 12px;\n}\n\n/* ===================================\n NOTIFICATIONS CONTENT\n =================================== */\n\n.notifications-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch; /* iPhone smooth scrolling */\n}\n\n/* Custom Scrollbar */\n.notifications-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.notifications-content::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-card);\n}\n\n.notifications-content::-webkit-scrollbar-thumb {\n background: var(--mj-border-default);\n border-radius: 4px;\n}\n\n.notifications-content::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-muted);\n}\n\n/* ===================================\n EMPTY STATE\n =================================== */\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 80px 32px;\n text-align: center;\n}\n\n.empty-icon {\n width: 96px;\n height: 96px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.empty-icon i {\n font-size: 40px;\n color: var(--mj-text-muted);\n}\n\n.empty-state h3 {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0 0 8px;\n}\n\n.empty-state p {\n font-size: 15px;\n color: var(--mj-text-secondary);\n margin: 0;\n max-width: 320px;\n line-height: 1.5;\n}\n\n/* ===================================\n NOTIFICATIONS LIST\n =================================== */\n\n.notifications-list {\n background: transparent;\n}\n\n/* ===================================\n NOTIFICATION CARD - iPhone UX Style\n =================================== */\n\n.notification-card {\n display: grid;\n grid-template-columns: 4px 56px 1fr auto;\n gap: 14px;\n align-items: start;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n}\n\n.notification-card:last-child {\n border-bottom: none;\n}\n\n.notification-card:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.notification-card.clickable {\n cursor: pointer;\n}\n\n.notification-card.clickable:active {\n background: var(--mj-bg-surface-sunken);\n transform: scale(0.995);\n}\n\n/* Unread State with Blue Highlight */\n.notification-card.unread {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.notification-card.unread:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-card));\n}\n\n/* Card Indicator - Blue Bar for Unread */\n.card-indicator {\n width: 4px;\n height: 100%;\n min-height: 64px;\n border-radius: 2px;\n background: transparent;\n transition: all 0.2s ease;\n align-self: stretch;\n}\n\n.notification-card.unread .card-indicator {\n background: var(--mj-brand-primary);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n/* Card Icon - Larger and More Prominent */\n.card-icon {\n width: 56px;\n height: 56px;\n border-radius: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s ease;\n}\n\n.notification-card:hover .card-icon {\n transform: scale(1.05);\n}\n\n.card-icon i {\n font-size: 24px;\n}\n\n/* Card Content */\n.card-content {\n flex: 1;\n min-width: 0;\n}\n\n.card-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 6px;\n}\n\n.card-title {\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin: 0;\n line-height: 1.4;\n word-wrap: break-word;\n}\n\n.card-title-unread {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.notification-card.clickable .card-title {\n color: var(--mj-brand-primary);\n}\n\n.notification-card.clickable:hover .card-title {\n text-decoration: underline;\n}\n\n.card-time {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.card-time i {\n font-size: 12px;\n}\n\n/* Card Meta */\n.card-meta {\n margin-bottom: 8px;\n}\n\n.card-type {\n display: inline-flex;\n align-items: center;\n padding: 4px 12px;\n border-radius: 9999px; /* Circular design */\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n/* Card Message */\n.card-message {\n font-size: 15px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n margin: 0;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Card Actions - Circular Buttons */\n.card-actions {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding-top: 6px;\n}\n\n.card-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border-radius: 9999px; /* Circular design */\n font-size: 13px;\n font-weight: 600;\n border: 2px solid var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n font-family: inherit;\n}\n\n.card-action-btn:hover {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: white;\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.card-action-btn:active {\n transform: translateY(0) scale(0.98);\n}\n\n.card-action-btn i {\n font-size: 13px;\n}\n\n/* ===================================\n ANIMATIONS\n =================================== */\n\n@keyframes slideInUp {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.notification-card {\n animation: slideInUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* ===================================\n ACCESSIBILITY\n =================================== */\n\nbutton:focus-visible,\ninput:focus-visible,\nselect:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* ===================================\n RESPONSIVE DESIGN - iPhone UX\n =================================== */\n\n/* iPad and smaller */\n@media (max-width: 768px) {\n .notifications-container {\n border-radius: 0;\n box-shadow: none;\n }\n\n .header-top {\n padding: 20px 20px 14px;\n }\n\n .title-icon {\n width: 44px;\n height: 44px;\n }\n\n .title-icon i {\n font-size: 20px;\n }\n\n .header-title h1 {\n font-size: 1.5rem;\n }\n\n /* Horizontal Slider on Mobile */\n .slider-content {\n padding: 14px 20px;\n gap: 10px;\n }\n\n .stat-pill {\n padding: 8px 16px;\n flex-shrink: 0;\n }\n\n .type-filter-slider {\n min-width: 160px;\n }\n\n .search-section {\n padding: 0 20px 14px;\n }\n\n .filter-info {\n padding: 0 20px 14px;\n }\n\n .notification-card {\n grid-template-columns: 4px 52px 1fr;\n gap: 12px;\n padding: 14px 16px;\n }\n\n .card-actions {\n grid-column: 2 / -1;\n padding-top: 10px;\n }\n\n .card-icon {\n width: 52px;\n height: 52px;\n }\n\n .card-icon i {\n font-size: 22px;\n }\n}\n\n/* iPhone SE and smaller */\n@media (max-width: 480px) {\n .header-top {\n flex-direction: column;\n align-items: stretch;\n gap: 12px;\n padding: 16px 16px 12px;\n }\n\n .header-title {\n justify-content: flex-start;\n }\n\n .title-icon {\n width: 40px;\n height: 40px;\n }\n\n .title-icon i {\n font-size: 18px;\n }\n\n .header-title h1 {\n font-size: 1.375rem;\n }\n\n .header-actions {\n width: 100%;\n justify-content: stretch;\n gap: 8px;\n }\n\n .action-btn {\n flex: 1;\n justify-content: center;\n padding: 10px 16px;\n font-size: 13px;\n }\n\n .btn-text {\n display: none;\n }\n\n /* Horizontal Slider - iPhone */\n .slider-content {\n padding: 12px 16px;\n gap: 8px;\n }\n\n .header-stats {\n gap: 8px;\n }\n\n .stat-pill {\n padding: 8px 14px;\n min-height: 40px;\n flex-shrink: 0;\n }\n\n .stat-label {\n font-size: 13px;\n }\n\n .stat-count {\n font-size: 12px;\n padding: 3px 8px;\n min-width: 24px;\n }\n\n .type-filter-slider {\n min-width: 140px;\n }\n\n .type-select,\n .search-input {\n font-size: 16px; /* Prevent iOS zoom on focus */\n }\n\n .search-section {\n padding: 0 16px 12px;\n }\n\n .filter-info {\n padding: 0 16px 12px;\n }\n\n .notification-card {\n grid-template-columns: 3px 48px 1fr;\n gap: 10px;\n padding: 12px 12px;\n }\n\n .card-indicator {\n width: 3px;\n min-height: 56px;\n }\n\n .card-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n }\n\n .card-icon i {\n font-size: 20px;\n }\n\n .card-title {\n font-size: 15px;\n }\n\n .card-time {\n font-size: 12px;\n }\n\n .card-message {\n font-size: 14px;\n -webkit-line-clamp: 2;\n }\n\n .card-type {\n font-size: 11px;\n padding: 3px 10px;\n }\n\n .card-actions {\n padding-top: 8px;\n gap: 6px;\n }\n\n .action-text {\n display: none;\n }\n\n .card-action-btn {\n padding: 8px 12px;\n min-width: 40px;\n justify-content: center;\n }\n\n .empty-state {\n padding: 60px 20px;\n }\n\n .empty-icon {\n width: 80px;\n height: 80px;\n }\n\n .empty-icon i {\n font-size: 32px;\n }\n\n .empty-state h3 {\n font-size: 18px;\n }\n\n .empty-state p {\n font-size: 14px;\n }\n}\n\n/* iPhone 12/13/14 Pro Max and similar */\n@media (min-width: 390px) and (max-width: 480px) {\n .btn-text {\n display: inline;\n }\n\n .action-btn {\n font-size: 14px;\n }\n}\n\n/* Dark mode support (if needed in future) */\n@media (prefers-color-scheme: dark) {\n /* Dark mode styles would go here */\n}\n"] }]
|
|
730
|
-
}], () => [{ type: i1.SharedService }, { type: i1.NavigationService }, { type: i2.ApplicationManager }],
|
|
731
|
-
|
|
732
|
-
args: ['allRadio']
|
|
733
|
-
}], unreadRadio: [{
|
|
734
|
-
type: ViewChild,
|
|
735
|
-
args: ['unreadRadio']
|
|
736
|
-
}], readRadio: [{
|
|
737
|
-
type: ViewChild,
|
|
738
|
-
args: ['readRadio']
|
|
739
|
-
}] }); })();
|
|
740
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserNotificationsComponent, { className: "UserNotificationsComponent", filePath: "src/lib/user-notifications/user-notifications.component.ts", lineNumber: 56 }); })();
|
|
918
|
+
args: [{ standalone: false, selector: 'app-user-notifications', template: "<div class=\"notifications-container\">\n <!-- Header Section -->\n <div class=\"notifications-header\">\n <div class=\"header-top\">\n <div class=\"header-title\">\n <div class=\"title-icon\">\n <i class=\"fa-solid fa-bell\"></i>\n </div>\n <div class=\"title-text\">\n <h1>Notifications</h1>\n @if (UnreadNotifications.length > 0) {\n <span class=\"title-subtitle\">{{UnreadNotifications.length}} unread</span>\n } @else if (AllNotifications.length > 0) {\n <span class=\"title-subtitle\">All caught up</span>\n }\n </div>\n </div>\n\n @if (AllNotifications.length > 0) {\n <div class=\"header-actions\">\n @if (UnreadNotifications.length > 0) {\n <button class=\"action-btn action-btn-ghost\"\n type=\"button\"\n (click)=\"markAllAsRead()\"\n aria-label=\"Mark all notifications as read\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Read</span>\n </button>\n }\n @if (ReadNotifications.length > 0) {\n <button class=\"action-btn action-btn-secondary\"\n type=\"button\"\n (click)=\"markAllAsUnread()\"\n aria-label=\"Mark all notifications as unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Mark All Unread</span>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Filters Section -->\n @if (AllNotifications.length > 0) {\n <div class=\"filters-section\">\n <div class=\"filters-slider\">\n <div class=\"slider-content\">\n <!-- Read-status pills -->\n <div class=\"header-stats\" role=\"group\" aria-label=\"Filter notifications by read status\">\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'All'\"\n (click)=\"selectReadOption('All')\"\n [attr.aria-pressed]=\"radioSelected === 'All'\"\n aria-label=\"Show all notifications\">\n <span class=\"stat-label\">All</span>\n <span class=\"stat-count\">{{AllNotifications.length}}</span>\n </button>\n\n @if (UnreadNotifications.length > 0 || ReadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Unread'\"\n [class.has-unread]=\"UnreadNotifications.length > 0\"\n (click)=\"selectReadOption('Unread')\"\n [attr.aria-pressed]=\"radioSelected === 'Unread'\"\n aria-label=\"Show unread notifications\">\n <span class=\"stat-label\">Unread</span>\n <span class=\"stat-count\" [class.unread-count]=\"UnreadNotifications.length > 0\">\n {{UnreadNotifications.length}}\n </span>\n </button>\n }\n\n @if (ReadNotifications.length > 0 || UnreadNotifications.length === 0) {\n <button class=\"stat-pill\"\n type=\"button\"\n [class.active]=\"radioSelected === 'Read'\"\n (click)=\"selectReadOption('Read')\"\n [attr.aria-pressed]=\"radioSelected === 'Read'\"\n aria-label=\"Show read notifications\">\n <span class=\"stat-label\">Read</span>\n <span class=\"stat-count\">{{ReadNotifications.length}}</span>\n </button>\n }\n </div>\n\n <!-- Type filter -->\n @if (notificationTypes.length > 0) {\n <div class=\"filter-item type-filter-slider\">\n <select class=\"type-select\"\n [(ngModel)]=\"selectedTypeFilter\"\n (change)=\"onTypeFilterChange(selectedTypeFilter)\"\n aria-label=\"Filter by notification type\">\n <option [value]=\"null\">All Types</option>\n @for (type of notificationTypes; track type.ID) {\n <option [value]=\"type.ID\">{{type.Name}}</option>\n }\n </select>\n </div>\n }\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-section\">\n <div class=\"search-container\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n class=\"search-input\"\n placeholder=\"Search notifications...\"\n [value]=\"currentFilter\"\n (input)=\"onFilterChanged($any($event.target).value)\"\n aria-label=\"Search notifications\" />\n </div>\n </div>\n\n @if (NotificationsToShow.length !== AllNotifications.length) {\n <div class=\"filter-info\">\n <span class=\"filter-badge\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Showing {{NotificationsToShow.length}} of {{AllNotifications.length}}\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Notifications Content -->\n <div class=\"notifications-content\">\n @if (NotificationsToShow.length === 0 && AllNotifications.length === 0) {\n <mj-empty-state\n Variant=\"success\"\n Icon=\"fa-solid fa-bell-slash\"\n Title=\"No Notifications\"\n Message=\"You're all caught up! New notifications will appear here.\" />\n } @else if (NotificationsToShow.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-filter-circle-xmark\"\n Title=\"No Matching Notifications\"\n Message=\"Try adjusting your filters to see more notifications.\" />\n } @else {\n <!-- Day-grouped notification list -->\n <div class=\"notifications-list\">\n @for (group of Groups; track group.Key) {\n <div class=\"group-label\">{{group.Label}}</div>\n\n @for (vm of group.Items; track vm.N.ID) {\n <article class=\"notification-card\"\n [class.unread]=\"vm.N.Unread\"\n [class.expanded]=\"IsExpanded(vm)\"\n [class.clickable]=\"vm.Clickable\"\n role=\"article\"\n [attr.aria-label]=\"vm.N.Title\">\n\n <!-- Unread Indicator Bar -->\n <div class=\"card-indicator\" aria-hidden=\"true\"></div>\n\n <!-- Type Icon -->\n <div class=\"card-icon\" aria-hidden=\"true\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.N)\"\n [style.color]=\"getTypeColor(vm.N)\"></i>\n </div>\n\n <!-- Content -->\n <div class=\"card-content\" (click)=\"notificationClicked(vm.N)\">\n <div class=\"card-header\">\n <h3 class=\"card-title\" [class.card-title-unread]=\"vm.N.Unread\">\n {{vm.N.Title}}\n </h3>\n <span class=\"card-time\" [title]=\"(vm.N.__mj_CreatedAt | date:'medium') ?? ''\">\n @if (vm.Relative) {\n {{vm.Relative}}\n } @else {\n <time [attr.datetime]=\"vm.N.__mj_CreatedAt\">{{vm.N.__mj_CreatedAt | date:'MMM d, h:mm a'}}</time>\n }\n </span>\n </div>\n\n <div class=\"card-meta\">\n <span class=\"card-type\">{{getTypeName(vm.N)}}</span>\n @if (vm.Clickable) {\n <span class=\"card-open-hint\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i> Open\n </span>\n }\n </div>\n\n @if (!IsExpanded(vm)) {\n <p class=\"card-message\">{{vm.Preview}}</p>\n } @else {\n <div class=\"card-rich\" (click)=\"$event.stopPropagation()\">\n @switch (vm.Kind) {\n @case ('html') {\n <!-- Angular sanitizes on [innerHTML] bind; chrome tags were stripped at classification -->\n <div class=\"card-rich-html\" [innerHTML]=\"vm.Body\"></div>\n }\n @case ('markdown') {\n <mj-markdown class=\"card-rich-md\" [data]=\"vm.Body\" [enableMermaid]=\"false\"></mj-markdown>\n }\n @default {\n <p class=\"card-message card-message-full\">{{vm.N.Message}}</p>\n }\n }\n </div>\n }\n\n @if (vm.Expandable) {\n <button class=\"card-expand-btn\" type=\"button\"\n (click)=\"ToggleExpanded(vm, $event)\"\n [attr.aria-expanded]=\"IsExpanded(vm)\">\n <i class=\"fa-solid\" [class.fa-chevron-down]=\"!IsExpanded(vm)\" [class.fa-chevron-up]=\"IsExpanded(vm)\" aria-hidden=\"true\"></i>\n {{ IsExpanded(vm) ? 'Show less' : 'Show more' }}\n </button>\n }\n </div>\n\n <!-- Actions -->\n <div class=\"card-actions\">\n @if (vm.N.Unread) {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, true, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as read'\"\n title=\"Mark as Read\">\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Read</span>\n </button>\n } @else {\n <button class=\"card-action-btn\"\n type=\"button\"\n (click)=\"markAsRead(vm.N, false, null)\"\n [attr.aria-label]=\"'Mark ' + vm.N.Title + ' as unread'\"\n title=\"Mark as Unread\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span class=\"action-text\">Unread</span>\n </button>\n }\n </div>\n </article>\n }\n }\n </div>\n }\n </div>\n</div>\n", styles: ["/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n User Notifications \u2014 day-grouped cards with rich (HTML/Markdown) content,\n expand/collapse, and token-driven theming (light + dark for free).\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n:host {\n display: block;\n height: 100%;\n}\n\n.notifications-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.notifications-header {\n flex-shrink: 0;\n padding: 20px 24px 12px 24px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.header-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 14px;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n\n.title-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: var(--mj-radius-lg, 12px);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.title-text {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.title-text h1 {\n margin: 0;\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.2;\n}\n\n.title-subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.action-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 12px;\n border-radius: var(--mj-radius-md, 8px);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.15s, color 0.15s, border-color 0.15s;\n}\n\n.action-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.action-btn-ghost {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.action-btn-ghost:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* \u2500\u2500 Filters \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.filters-section {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n}\n\n.filters-slider {\n min-width: 0;\n}\n\n.slider-content {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.header-stats {\n display: inline-flex;\n gap: 4px;\n padding: 3px;\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-bg-surface-sunken);\n}\n\n.stat-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border: none;\n border-radius: var(--mj-radius-full, 999px);\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.15s, color 0.15s;\n}\n\n.stat-pill:hover {\n color: var(--mj-text-primary);\n}\n\n.stat-pill.active {\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.stat-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--mj-radius-full, 999px);\n background: color-mix(in srgb, var(--mj-text-muted) 14%, transparent);\n color: var(--mj-text-secondary);\n font-size: 10px;\n font-weight: 700;\n}\n\n.stat-count.unread-count {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.type-select {\n padding: 7px 10px;\n border-radius: var(--mj-radius-md, 8px);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.search-section {\n flex: 1 1 220px;\n min-width: 180px;\n}\n\n.search-container {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-icon {\n position: absolute;\n left: 12px;\n color: var(--mj-text-muted);\n font-size: 12px;\n pointer-events: none;\n}\n\n.search-input {\n width: 100%;\n padding: 8px 12px 8px 32px;\n border-radius: var(--mj-radius-md, 8px);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: 13px;\n}\n\n.search-input:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.filter-info {\n flex-basis: 100%;\n}\n\n.filter-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: var(--mj-radius-full, 999px);\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n font-size: 11px;\n font-weight: 600;\n}\n\n/* \u2500\u2500 Content / list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.notifications-content {\n flex: 1 1 auto;\n min-height: 0;\n overflow-y: auto;\n padding: 16px 24px 32px 24px;\n}\n\n.notifications-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n max-width: 960px;\n margin: 0 auto;\n}\n\n.group-label {\n position: sticky;\n top: -16px;\n z-index: 1;\n padding: 10px 2px 4px 2px;\n background: var(--mj-bg-page);\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--mj-text-muted);\n}\n\n.group-label:not(:first-child) {\n margin-top: 8px;\n}\n\n/* \u2500\u2500 Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.notification-card {\n position: relative;\n display: flex;\n gap: 12px;\n padding: 14px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg, 12px);\n background: var(--mj-bg-surface);\n transition: border-color 0.15s, box-shadow 0.15s, background-color 0.15s;\n overflow: hidden;\n}\n\n.notification-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.notification-card.unread {\n background: color-mix(in srgb, var(--mj-brand-primary) 3%, var(--mj-bg-surface));\n}\n\n.card-indicator {\n display: none;\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background: var(--mj-brand-primary);\n border-radius: 0 2px 2px 0;\n}\n\n.notification-card.unread .card-indicator {\n display: block;\n}\n\n.card-icon {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border-radius: var(--mj-radius-md, 10px);\n background: var(--mj-bg-surface-sunken);\n font-size: 14px;\n}\n\n.card-content {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.notification-card.clickable .card-content {\n cursor: pointer;\n}\n\n.card-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 12px;\n}\n\n.card-title {\n margin: 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow-wrap: anywhere;\n}\n\n.card-title-unread {\n font-weight: 700;\n}\n\n.card-time {\n flex-shrink: 0;\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 3px 0 6px 0;\n}\n\n.card-type {\n display: inline-flex;\n padding: 2px 8px;\n border-radius: var(--mj-radius-full, 999px);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.card-open-hint {\n display: none;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.notification-card.clickable:hover .card-open-hint {\n display: inline-flex;\n}\n\n.card-message {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--mj-text-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n\n.card-message-full {\n display: block;\n -webkit-line-clamp: unset;\n white-space: pre-wrap;\n}\n\n/* \u2500\u2500 Rich (expanded) content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.card-rich {\n margin-top: 4px;\n padding: 12px 14px;\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-card);\n cursor: default;\n}\n\n/* Sanitized foreign markup: keep it inside the card no matter what it brought along */\n.card-rich-html {\n font-size: 13px;\n line-height: 1.55;\n color: var(--mj-text-primary);\n overflow-x: auto;\n}\n\n.card-rich-html img {\n max-width: 100%;\n height: auto;\n}\n\n.card-rich-html table {\n max-width: 100%;\n border-collapse: collapse;\n}\n\n.card-rich-html td,\n.card-rich-html th {\n padding: 4px 8px;\n border: 1px solid var(--mj-border-subtle);\n}\n\n.card-rich-html a {\n color: var(--mj-text-link);\n}\n\n.card-rich-html h1,\n.card-rich-html h2,\n.card-rich-html h3 {\n margin: 0.4em 0 0.3em 0;\n font-size: 1.05em;\n}\n\n.card-rich-md {\n display: block;\n font-size: 13px;\n}\n\n.card-expand-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-top: 8px;\n padding: 4px 10px;\n border: none;\n border-radius: var(--mj-radius-full, 999px);\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 11px;\n font-weight: 700;\n cursor: pointer;\n}\n\n.card-expand-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n/* \u2500\u2500 Card actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.card-actions {\n flex-shrink: 0;\n display: flex;\n align-items: flex-start;\n}\n\n.card-action-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n border: 1px solid transparent;\n border-radius: var(--mj-radius-md, 8px);\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 600;\n cursor: pointer;\n transition: background-color 0.15s, color 0.15s;\n}\n\n.card-action-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-default);\n}\n\n/* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@media (max-width: 720px) {\n .notifications-header {\n padding: 14px 14px 10px 14px;\n }\n\n .notifications-content {\n padding: 12px 12px 24px 12px;\n }\n\n .btn-text,\n .action-text {\n display: none;\n }\n\n .card-header {\n flex-direction: column;\n gap: 2px;\n }\n\n .card-time {\n order: -1;\n }\n}\n"] }]
|
|
919
|
+
}], () => [{ type: i1.SharedService }, { type: i1.NavigationService }, { type: i2.ApplicationManager }], null); })();
|
|
920
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserNotificationsComponent, { className: "UserNotificationsComponent", filePath: "src/lib/user-notifications/user-notifications.component.ts", lineNumber: 93 }); })();
|
|
741
921
|
//# sourceMappingURL=user-notifications.component.js.map
|