@adarshctas/live-notification 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,64 +1,89 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @adarshctas/notification1
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Angular notification library for showing notifications/messages in Angular applications.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Install the package using npm:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
npm install @adarshctas/live-notification
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## 🚀 Features
|
|
14
|
+
🔔 Real-time notifications using Socket.IO
|
|
15
|
+
📡 REST API support (send / fetch / mark as read)
|
|
16
|
+
🍞 Toast notifications (success, error, warning, info)
|
|
17
|
+
📊 Multiple notification modes (alert / toast / in-app)
|
|
18
|
+
🎯 Filter notifications by type
|
|
19
|
+
✅ Mark notifications as read
|
|
20
|
+
🔌 Easy integration in Angular apps
|
|
21
|
+
🧹 Auto cleanup socket listeners
|
|
22
|
+
|
|
23
|
+
## Dependencies
|
|
24
|
+
|
|
25
|
+
This package requires:
|
|
14
26
|
|
|
15
27
|
```bash
|
|
16
|
-
|
|
28
|
+
"@angular/core": ">=15.0.0",
|
|
29
|
+
"@angular/common": ">=15.0.0",
|
|
30
|
+
"@angular/common/http": ">=15.0.0",
|
|
31
|
+
"rxjs": ">=6.5.0"
|
|
17
32
|
```
|
|
18
33
|
|
|
19
|
-
##
|
|
34
|
+
## How to use
|
|
20
35
|
|
|
21
|
-
|
|
36
|
+
1 Import the notification service:
|
|
22
37
|
|
|
23
|
-
```
|
|
24
|
-
|
|
38
|
+
```ts
|
|
39
|
+
import { Notification } from '@adarshctas/live-notification';
|
|
25
40
|
```
|
|
26
41
|
|
|
27
|
-
|
|
42
|
+
2 Use inside component:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
constructor(private notification: Notification) {}
|
|
46
|
+
```
|
|
28
47
|
|
|
29
|
-
|
|
48
|
+
3 Initialize (recommended)
|
|
30
49
|
|
|
31
|
-
|
|
50
|
+
```ts
|
|
51
|
+
ngOnInit() {
|
|
32
52
|
|
|
33
|
-
|
|
53
|
+
this.notification.listenNotification().subscribe(data => {
|
|
54
|
+
console.log('New Notification:', data);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
```
|
|
34
58
|
|
|
35
|
-
|
|
36
|
-
cd dist/live-notification
|
|
37
|
-
```
|
|
59
|
+
## Example Use Case
|
|
38
60
|
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm publish
|
|
42
|
-
```
|
|
61
|
+
Show a success notification after saving data:
|
|
43
62
|
|
|
44
|
-
|
|
63
|
+
```ts
|
|
64
|
+
setToastMode() {
|
|
65
|
+
this.notification.setActiveType('toast');
|
|
66
|
+
}
|
|
45
67
|
|
|
46
|
-
|
|
68
|
+
setAlertMode() {
|
|
69
|
+
this.notification.setActiveType('alert');
|
|
70
|
+
}
|
|
47
71
|
|
|
48
|
-
|
|
49
|
-
|
|
72
|
+
setInAppMode() {
|
|
73
|
+
this.notification.setActiveType('inapp');
|
|
74
|
+
}
|
|
50
75
|
```
|
|
51
76
|
|
|
52
|
-
##
|
|
77
|
+
## 🎯 Summary
|
|
53
78
|
|
|
54
|
-
|
|
79
|
+
show() → Simple alert notification
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
toast() → Temporary popup message
|
|
82
|
+
|
|
83
|
+
notify() → Structured in-app notification
|
|
59
84
|
|
|
60
|
-
|
|
85
|
+
requestPermission() → Browser notification permission
|
|
61
86
|
|
|
62
|
-
##
|
|
87
|
+
## 📄 License
|
|
63
88
|
|
|
64
|
-
|
|
89
|
+
MIT © Adarsh Ctasis LLP
|
|
@@ -1,22 +1,297 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Component } from '@angular/core';
|
|
2
|
+
import { Injectable, Component, PLATFORM_ID, Inject } from '@angular/core';
|
|
3
|
+
import { Observable, Subject, interval } from 'rxjs';
|
|
4
|
+
import { io } from 'socket.io-client';
|
|
5
|
+
import * as i1 from '@angular/common/http';
|
|
6
|
+
import * as i2$1 from '@angular/common';
|
|
7
|
+
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
8
|
+
import * as i2 from '@angular/forms';
|
|
9
|
+
import { FormsModule } from '@angular/forms';
|
|
3
10
|
|
|
4
|
-
class
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
class Notification {
|
|
12
|
+
http;
|
|
13
|
+
receiver;
|
|
14
|
+
/** Used by receiver component to expose a callback for sender actions. */
|
|
15
|
+
registerReceiver(receiver) {
|
|
16
|
+
this.receiver = receiver;
|
|
17
|
+
}
|
|
18
|
+
setActiveType(type) {
|
|
19
|
+
this.receiver?.setActiveType(type);
|
|
20
|
+
}
|
|
21
|
+
static socketInstance;
|
|
22
|
+
socket;
|
|
23
|
+
// BASE URL
|
|
24
|
+
apiUrl = 'http://localhost:3000/api/notifications';
|
|
25
|
+
constructor(http) {
|
|
26
|
+
this.http = http;
|
|
27
|
+
if (!Notification.socketInstance) {
|
|
28
|
+
Notification.socketInstance = io('http://localhost:3000');
|
|
29
|
+
}
|
|
30
|
+
this.socket = Notification.socketInstance;
|
|
31
|
+
}
|
|
32
|
+
// SEND NOTIFICATION
|
|
33
|
+
sendNotification(data) {
|
|
34
|
+
return this.http.post(`${this.apiUrl}/send`, data);
|
|
35
|
+
}
|
|
36
|
+
// GET ALL NOTIFICATIONS
|
|
37
|
+
getAll() {
|
|
38
|
+
return this.http.get(`${this.apiUrl}/all`);
|
|
39
|
+
}
|
|
40
|
+
// REALTIME LISTENER
|
|
41
|
+
listenNotification() {
|
|
42
|
+
return new Observable((observer) => {
|
|
43
|
+
const handler = (data) => observer.next(data);
|
|
44
|
+
this.socket.on('notification', handler);
|
|
45
|
+
return () => {
|
|
46
|
+
this.socket.off('notification', handler);
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
listenNotificationByType(type) {
|
|
51
|
+
return new Observable((observer) => {
|
|
52
|
+
const eventName = `notification:${type}`;
|
|
53
|
+
const handler = (data) => observer.next(data);
|
|
54
|
+
this.socket.on(eventName, handler);
|
|
55
|
+
return () => {
|
|
56
|
+
this.socket.off(eventName, handler);
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// MARK AS READ
|
|
61
|
+
markAsRead(id) {
|
|
62
|
+
return this.http.put(`${this.apiUrl}/read/${id}`, { isRead: true });
|
|
63
|
+
}
|
|
64
|
+
toastSubject = new Subject();
|
|
65
|
+
toast$ = this.toastSubject.asObservable();
|
|
66
|
+
emitToast(message, type) {
|
|
67
|
+
this.toastSubject.next({ message, type });
|
|
68
|
+
}
|
|
69
|
+
success(msg) {
|
|
70
|
+
this.emitToast(msg, 'success');
|
|
71
|
+
}
|
|
72
|
+
error(msg) {
|
|
73
|
+
this.emitToast(msg, 'error');
|
|
74
|
+
}
|
|
75
|
+
warning(msg) {
|
|
76
|
+
this.emitToast(msg, 'warning');
|
|
77
|
+
}
|
|
78
|
+
info(msg) {
|
|
79
|
+
this.emitToast(msg, 'info');
|
|
80
|
+
}
|
|
81
|
+
disconnectSocket() {
|
|
82
|
+
if (this.socket) {
|
|
83
|
+
this.socket.disconnect();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: Notification, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
87
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: Notification, providedIn: 'root' });
|
|
7
88
|
}
|
|
8
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type:
|
|
89
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: Notification, decorators: [{
|
|
90
|
+
type: Injectable,
|
|
91
|
+
args: [{
|
|
92
|
+
providedIn: 'root',
|
|
93
|
+
}]
|
|
94
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
95
|
+
|
|
96
|
+
class Sender {
|
|
97
|
+
notificationService;
|
|
98
|
+
cd;
|
|
99
|
+
message = '';
|
|
100
|
+
constructor(notificationService, cd) {
|
|
101
|
+
this.notificationService = notificationService;
|
|
102
|
+
this.cd = cd;
|
|
103
|
+
}
|
|
104
|
+
send(type, level = 'INFO') {
|
|
105
|
+
if (!this.message.trim()) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const payload = {
|
|
109
|
+
type: type,
|
|
110
|
+
level: level,
|
|
111
|
+
message: this.message,
|
|
112
|
+
userId: 'global'
|
|
113
|
+
};
|
|
114
|
+
// No realtime updates while typing.
|
|
115
|
+
// Receiver will only update the selected section based on button click.
|
|
116
|
+
this.notificationService.setActiveType?.(type);
|
|
117
|
+
this.notificationService.sendNotification(payload).subscribe({
|
|
118
|
+
next: () => {
|
|
119
|
+
this.message = '';
|
|
120
|
+
},
|
|
121
|
+
error: (err) => {
|
|
122
|
+
console.error('Notification send error:', err);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: Sender, deps: [{ token: Notification }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
127
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: Sender, isStandalone: true, selector: "app-sender", ngImport: i0, template: "<div class=\"sender-container\">\n\n \n <div class=\"card\">\n \n <h2 class=\"title\">\uD83D\uDCE4 Sender Panel</h2>\n\n <p class=\"subtitle\">\n Send real-time notifications instantly\n </p>\n\n <!-- Input -->\n <div class=\"input-box\">\n\n <input\n type=\"text\"\n placeholder=\"Enter notification message...\"\n [(ngModel)]=\"message\"\n (keydown.enter)=\"$event.preventDefault()\"\n />\n\n </div>\n\n <!-- Buttons -->\n <div class=\"btn-group\">\n\n <button\n type=\"button\"\n class=\"alert-btn\"\n (click)=\"send('alert')\"\n [disabled]=\"!message.trim()\"\n >\n \uD83D\uDEA8 Send Alert\n </button>\n\n <button\n type=\"button\"\n class=\"toast-btn\"\n (click)=\"send('toast')\"\n [disabled]=\"!message.trim()\"\n >\n \uD83C\uDF5E Send Toast\n </button>\n<div class=\"btn\">\n <button (click)=\"send('toast', 'SUCCESS')\">Success</button>\n <button (click)=\"send('toast', 'ERROR')\">Error</button>\n <button (click)=\"send('toast', 'WARNING')\">Warning</button>\n <button (click)=\"send('toast', 'INFO')\">Info</button>\n</div>\n <button\n type=\"button\"\n class=\"inapp-btn\"\n (click)=\"send('inapp')\"\n [disabled]=\"!message.trim()\"\n >\n \uD83D\uDD14 Send In-App\n </button>\n\n </div>\n\n </div>\n\n</div>", styles: [".sender-container{min-height:100vh;display:flex;justify-content:center;align-items:center;padding:20px;font-family:Arial,sans-serif}.card{width:420px;background:#fff;padding:25px;border-radius:16px;box-shadow:0 10px 30px #0003;animation:fadeIn .5s ease-in-out}.title{color:#312f2f;text-align:center;font-size:22px;margin-bottom:5px}.subtitle{text-align:center;font-size:13px;color:#666;margin-bottom:20px}.input-box input{width:100%;padding:12px;border-radius:10px;border:1px solid #ddd;outline:none;transition:.3s}.input-box input:focus{border-color:#667eea;box-shadow:0 0 5px #667eea80}.btn-group{display:flex;flex-direction:column;gap:10px;margin-top:15px}button{padding:12px;border:none;border-radius:10px;cursor:pointer;font-weight:700;transition:.3s}.alert-btn{background:#ff4d4dd5}.toast-btn{background:#ffa602d0}.inapp-btn{background:#2ed574c8}button:hover{transform:scale(1.03);opacity:.9}button:disabled{opacity:.5;cursor:not-allowed}@keyframes fadeIn{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.btn{display:flex;gap:12px;flex-wrap:wrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
128
|
+
}
|
|
129
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: Sender, decorators: [{
|
|
9
130
|
type: Component,
|
|
10
|
-
args: [{ selector: '
|
|
11
|
-
}] });
|
|
131
|
+
args: [{ selector: 'app-sender', imports: [CommonModule, FormsModule], template: "<div class=\"sender-container\">\n\n \n <div class=\"card\">\n \n <h2 class=\"title\">\uD83D\uDCE4 Sender Panel</h2>\n\n <p class=\"subtitle\">\n Send real-time notifications instantly\n </p>\n\n <!-- Input -->\n <div class=\"input-box\">\n\n <input\n type=\"text\"\n placeholder=\"Enter notification message...\"\n [(ngModel)]=\"message\"\n (keydown.enter)=\"$event.preventDefault()\"\n />\n\n </div>\n\n <!-- Buttons -->\n <div class=\"btn-group\">\n\n <button\n type=\"button\"\n class=\"alert-btn\"\n (click)=\"send('alert')\"\n [disabled]=\"!message.trim()\"\n >\n \uD83D\uDEA8 Send Alert\n </button>\n\n <button\n type=\"button\"\n class=\"toast-btn\"\n (click)=\"send('toast')\"\n [disabled]=\"!message.trim()\"\n >\n \uD83C\uDF5E Send Toast\n </button>\n<div class=\"btn\">\n <button (click)=\"send('toast', 'SUCCESS')\">Success</button>\n <button (click)=\"send('toast', 'ERROR')\">Error</button>\n <button (click)=\"send('toast', 'WARNING')\">Warning</button>\n <button (click)=\"send('toast', 'INFO')\">Info</button>\n</div>\n <button\n type=\"button\"\n class=\"inapp-btn\"\n (click)=\"send('inapp')\"\n [disabled]=\"!message.trim()\"\n >\n \uD83D\uDD14 Send In-App\n </button>\n\n </div>\n\n </div>\n\n</div>", styles: [".sender-container{min-height:100vh;display:flex;justify-content:center;align-items:center;padding:20px;font-family:Arial,sans-serif}.card{width:420px;background:#fff;padding:25px;border-radius:16px;box-shadow:0 10px 30px #0003;animation:fadeIn .5s ease-in-out}.title{color:#312f2f;text-align:center;font-size:22px;margin-bottom:5px}.subtitle{text-align:center;font-size:13px;color:#666;margin-bottom:20px}.input-box input{width:100%;padding:12px;border-radius:10px;border:1px solid #ddd;outline:none;transition:.3s}.input-box input:focus{border-color:#667eea;box-shadow:0 0 5px #667eea80}.btn-group{display:flex;flex-direction:column;gap:10px;margin-top:15px}button{padding:12px;border:none;border-radius:10px;cursor:pointer;font-weight:700;transition:.3s}.alert-btn{background:#ff4d4dd5}.toast-btn{background:#ffa602d0}.inapp-btn{background:#2ed574c8}button:hover{transform:scale(1.03);opacity:.9}button:disabled{opacity:.5;cursor:not-allowed}@keyframes fadeIn{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.btn{display:flex;gap:12px;flex-wrap:wrap}\n"] }]
|
|
132
|
+
}], ctorParameters: () => [{ type: Notification }, { type: i0.ChangeDetectorRef }] });
|
|
12
133
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
134
|
+
class ReceiverComponent {
|
|
135
|
+
notificationService;
|
|
136
|
+
cd;
|
|
137
|
+
platformId;
|
|
138
|
+
alerts = [];
|
|
139
|
+
toasts = [];
|
|
140
|
+
inapps = [];
|
|
141
|
+
showToast = false;
|
|
142
|
+
liveToastMessage = '';
|
|
143
|
+
toastClass = 'toast-info';
|
|
144
|
+
activeTab = null;
|
|
145
|
+
refreshSub;
|
|
146
|
+
toastSub;
|
|
147
|
+
inappSub;
|
|
148
|
+
alertSub;
|
|
149
|
+
constructor(notificationService, cd, platformId) {
|
|
150
|
+
this.notificationService = notificationService;
|
|
151
|
+
this.cd = cd;
|
|
152
|
+
this.platformId = platformId;
|
|
153
|
+
}
|
|
154
|
+
// =========================
|
|
155
|
+
// INIT
|
|
156
|
+
// =========================
|
|
157
|
+
ngOnInit() {
|
|
158
|
+
this.notificationService.registerReceiver(this);
|
|
159
|
+
this.loadData();
|
|
160
|
+
this.refreshSub = interval(3000).subscribe(() => {
|
|
161
|
+
this.loadData();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
setActiveType(type) {
|
|
165
|
+
this.activeTab = type;
|
|
166
|
+
this.markTabAsRead(type);
|
|
167
|
+
this.cd.detectChanges();
|
|
168
|
+
}
|
|
169
|
+
// =========================
|
|
170
|
+
// LOAD ALL DATA
|
|
171
|
+
// =========================
|
|
172
|
+
loadData() {
|
|
173
|
+
this.notificationService.getAll().subscribe({
|
|
174
|
+
next: (res) => {
|
|
175
|
+
const data = res.data || [];
|
|
176
|
+
this.alerts = data.filter((n) => n.type === 'alert');
|
|
177
|
+
this.toasts = data.filter((n) => n.type === 'toast');
|
|
178
|
+
this.inapps = data.filter((n) => n.type === 'inapp');
|
|
179
|
+
this.cd.detectChanges();
|
|
180
|
+
},
|
|
181
|
+
error: (err) => {
|
|
182
|
+
console.error('Load notification error:', err);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// =========================
|
|
187
|
+
// AFTER VIEW (REALTIME)
|
|
188
|
+
// =========================
|
|
189
|
+
ngAfterViewInit() {
|
|
190
|
+
if (!isPlatformBrowser(this.platformId))
|
|
191
|
+
return;
|
|
192
|
+
if ('Notification' in window) {
|
|
193
|
+
window.Notification.requestPermission();
|
|
194
|
+
}
|
|
195
|
+
// ALERT
|
|
196
|
+
this.alertSub = this.notificationService
|
|
197
|
+
.listenNotificationByType('alert')
|
|
198
|
+
.subscribe((data) => {
|
|
199
|
+
if (!this.alerts.find(n => n._id === data._id)) {
|
|
200
|
+
this.alerts.unshift(data);
|
|
201
|
+
}
|
|
202
|
+
alert(`🚨 ALERT\n\n${data.message}`);
|
|
203
|
+
this.cd.detectChanges();
|
|
204
|
+
});
|
|
205
|
+
// TOAST
|
|
206
|
+
this.toastSub = this.notificationService
|
|
207
|
+
.listenNotificationByType('toast')
|
|
208
|
+
.subscribe((data) => {
|
|
209
|
+
if (!this.toasts.find(n => n._id === data._id)) {
|
|
210
|
+
this.toasts.unshift(data);
|
|
211
|
+
}
|
|
212
|
+
this.liveToastMessage = data.message;
|
|
213
|
+
this.toastClass = this.getToastClass(data.level);
|
|
214
|
+
this.showToast = true;
|
|
215
|
+
setTimeout(() => {
|
|
216
|
+
this.showToast = false;
|
|
217
|
+
this.cd.detectChanges();
|
|
218
|
+
}, 3000);
|
|
219
|
+
this.cd.detectChanges();
|
|
220
|
+
});
|
|
221
|
+
// INAPP
|
|
222
|
+
this.inappSub = this.notificationService
|
|
223
|
+
.listenNotificationByType('inapp')
|
|
224
|
+
.subscribe((data) => {
|
|
225
|
+
this.inapps.unshift(data);
|
|
226
|
+
if ('Notification' in window &&
|
|
227
|
+
window.Notification.permission === 'granted') {
|
|
228
|
+
new window.Notification('🔔 New Notification', {
|
|
229
|
+
body: data.message,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
this.cd.detectChanges();
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// =========================
|
|
236
|
+
// MARK AS READ (IMPORTANT)
|
|
237
|
+
// =========================
|
|
238
|
+
markTabAsRead(type) {
|
|
239
|
+
let list = [];
|
|
240
|
+
if (type === 'alert')
|
|
241
|
+
list = this.alerts;
|
|
242
|
+
if (type === 'toast')
|
|
243
|
+
list = this.toasts;
|
|
244
|
+
if (type === 'inapp')
|
|
245
|
+
list = this.inapps;
|
|
246
|
+
list.forEach(n => {
|
|
247
|
+
if (!n.isRead) {
|
|
248
|
+
n.isRead = true;
|
|
249
|
+
// backend update (optional)
|
|
250
|
+
this.notificationService.markAsRead(n._id).subscribe({
|
|
251
|
+
error: (err) => console.error(err)
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
this.cd.detectChanges();
|
|
256
|
+
}
|
|
257
|
+
// =========================
|
|
258
|
+
// CLEANUP
|
|
259
|
+
// =========================
|
|
260
|
+
ngOnDestroy() {
|
|
261
|
+
this.alertSub?.unsubscribe();
|
|
262
|
+
this.toastSub?.unsubscribe();
|
|
263
|
+
this.inappSub?.unsubscribe();
|
|
264
|
+
this.refreshSub?.unsubscribe();
|
|
265
|
+
this.notificationService.disconnectSocket?.();
|
|
266
|
+
}
|
|
267
|
+
getToastClass(level) {
|
|
268
|
+
switch (level) {
|
|
269
|
+
case 'SUCCESS':
|
|
270
|
+
return 'toast-success';
|
|
271
|
+
case 'ERROR':
|
|
272
|
+
return 'toast-error';
|
|
273
|
+
case 'WARNING':
|
|
274
|
+
return 'toast-warning';
|
|
275
|
+
case 'INFO':
|
|
276
|
+
return 'toast-info';
|
|
277
|
+
default:
|
|
278
|
+
return 'toast-info';
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ReceiverComponent, deps: [{ token: Notification }, { token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|
282
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.13", type: ReceiverComponent, isStandalone: true, selector: "lib-receiver", ngImport: i0, template: "<div class=\"receiver-container\">\n\n <!-- BUTTONS -->\n <div class=\"btn-group\">\n\n <button \n [class.active]=\"activeTab === 'alert'\" \n (click)=\"activeTab = 'alert'; markTabAsRead('alert')\">Show Alerts\n <span class=\"badge-count\"\n *ngIf=\"alerts.filter(n => !n.isRead).length > 0\">\n {{ alerts.filter(n => !n.isRead).length }}\n </span>\n </button>\n\n <button \n [class.active]=\"activeTab === 'toast'\" \n (click)=\"activeTab = 'toast'; markTabAsRead('toast')\">Show Toast\n <span class=\"badge-count\"\n *ngIf=\"toasts.filter(n => !n.isRead).length > 0\">\n {{ toasts.filter(n => !n.isRead).length }}\n </span>\n </button>\n\n <button \n [class.active]=\"activeTab === 'inapp'\" \n (click)=\"activeTab = 'inapp'; markTabAsRead('inapp')\">Show Notifications\n <span class=\"badge-count\"\n *ngIf=\"inapps.filter(n => !n.isRead).length > 0\">\n {{ inapps.filter(n => !n.isRead).length }}\n </span>\n\n </button>\n\n </div>\n\n <!-- LIVE TOAST -->\n <div class=\"live-toast\" *ngIf=\"showToast\">\n <div class=\"toast-popup\" [class]=\"toastClass\">\n \uD83C\uDF5E {{ liveToastMessage }}\n </div>\n </div>\n\n <div class=\"receiver-card\">\n\n <h2 class=\"title\">\uD83D\uDCE5 Receiver Panel</h2>\n <p class=\"subtitle\">Live incoming notifications</p>\n\n <!-- ALERT -->\n <div class=\"section\" *ngIf=\"activeTab === 'alert'\">\n <h3 class=\"section-title alert-title\">\uD83D\uDEA8 Alerts</h3>\n\n <div *ngFor=\"let n of alerts\">\n <div class=\"notification-card alert\">\n <div class=\"top-row\">\n <div class=\"badge\">ALERT</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n <!-- TOAST -->\n <div class=\"section\" *ngIf=\"activeTab === 'toast'\">\n <h3 class=\"section-title toast-title\">\uD83C\uDF5E Toast</h3>\n\n <div *ngFor=\"let n of toasts\">\n <div class=\"notification-card toast\">\n <div class=\"top-row\">\n <div class=\"badge\">TOAST</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n <!-- INAPP -->\n <div class=\"section\" *ngIf=\"activeTab === 'inapp'\">\n <h3 class=\"section-title inapp-title\">\uD83D\uDD14 In-App Notifications</h3>\n\n <div *ngFor=\"let n of inapps\">\n <div class=\"notification-card inapp\">\n <div class=\"top-row\">\n <div class=\"badge\">IN-APP</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n </div>\n</div>", styles: [".receiver-container{min-height:100vh;padding:24px;font-family:system-ui,sans-serif;transition:background .3s ease,color .3s ease}.light-theme{background:#f5f7fb;color:#111827}.light-theme .receiver-card{background:#fff;border:1px solid #e5e7eb;color:#111827}.light-theme .btn-group{background:#fff;border:1px solid #e5e7eb}.light-theme .btn-group button{color:#111827;background:transparent}.light-theme .btn-group button:hover{background:#f3f4f6}.light-theme .btn-group button.active{background:#2563eb;color:#fff}.light-theme .notification-card{background:#fff;border:1px solid #e5e7eb;color:#111827}.light-theme .message,.light-theme .time,.light-theme .subtitle{color:#111827}.dark-theme{background:#0b1220;color:#f9fafb}.dark-theme .receiver-card{background:#111827;border:1px solid #1f2937;color:#f9fafb}.dark-theme .btn-group{background:#111827;border:1px solid #1f2937}.dark-theme .btn-group button{color:#d1d5db;background:transparent}.dark-theme .btn-group button:hover{background:#1f2937}.dark-theme .btn-group button.active{background:#3b82f6;color:#fff}.dark-theme .notification-card{background:#0f172a;border:1px solid #1f2937;color:#f9fafb}.dark-theme .message,.dark-theme .time,.dark-theme .subtitle{color:#f9fafb}.btn-group{display:flex;gap:12px;padding:10px;border-radius:12px;width:fit-content;margin:0 auto 20px}.btn-group button{position:relative;border:none;padding:10px 16px;border-radius:10px;cursor:pointer;font-weight:600;transition:all .2s ease}.badge-count{position:absolute;top:-6px;right:-6px;background:#ef4444;color:#fff;font-size:11px;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center}.receiver-card{max-width:900px;margin:auto;padding:20px;border-radius:14px}.notification-card{padding:14px;border-radius:10px;margin-bottom:12px;transition:transform .2s ease}.notification-card:hover{transform:translateY(-2px)}.message{font-size:14px;line-height:1.5;word-break:break-word}.time{font-size:12px}.receiver-card{max-width:900px;margin:auto;padding:22px;border-radius:16px;transition:all .3s ease;background:#ffffff05;box-shadow:0 10px 25px #00000040,0 0 0 1px #ffffff0a,0 0 40px #3b82f626}.receiver-card:hover{transform:translateY(-3px);box-shadow:0 15px 35px #00000059,0 0 0 1px #ffffff0f,0 0 60px #6366f140}.dark-theme .receiver-card{background:#0f172a;box-shadow:0 15px 40px #0009,0 0 0 1px #ffffff0d,0 0 50px #3b82f633}.light-theme .receiver-card{background:#fff;box-shadow:0 10px 25px #00000014,0 0 0 1px #0000000d,0 0 30px #3b82f614}.notification-card.alert{border-left:4px solid #ef4444;background:#ef44440f;box-shadow:0 8px 20px #00000040,0 0 0 1px #ef444426,0 0 25px #ef444440}.notification-card.alert:hover{transform:translateY(-3px);box-shadow:0 12px 30px #00000059,0 0 0 1px #ef444440,0 0 40px #ef444466}.notification-card.toast{border-left:4px solid #f59e0b;background:#f59e0b0f;box-shadow:0 8px 20px #00000038,0 0 0 1px #f59e0b2e,0 0 25px #f59e0b38}.notification-card.toast:hover{transform:translateY(-3px);box-shadow:0 12px 30px #0000004d,0 0 0 1px #f59e0b4d,0 0 40px #f59e0b59}.notification-card.inapp{border-left:4px solid #3b82f6;background:#3b82f60f;box-shadow:0 8px 20px #00000038,0 0 0 1px #3b82f62e,0 0 25px #3b82f638}.notification-card.inapp:hover{transform:translateY(-3px);box-shadow:0 12px 30px #0000004d,0 0 0 1px #3b82f64d,0 0 40px #3b82f659}.receiver-container{padding:20px;min-height:100vh;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.btn-group{display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap}.btn-group button{position:relative;padding:10px 16px;border-radius:12px;border:1px solid rgba(255,255,255,.1);background:#ffffff0f;cursor:pointer;transition:.25s ease;font-weight:500;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.btn-group button:hover{transform:translateY(-2px);background:#ffffff1a}.btn-group button.active{background:linear-gradient(135deg,#6366f1,#3b82f6);border:none;box-shadow:0 10px 25px #3b82f64d}.badge-count{margin-left:8px;background:#ef4444;color:#fff;font-size:12px;padding:2px 7px;border-radius:999px;position:absolute;top:-6px;right:-6px;box-shadow:0 4px 10px #0000004d}.live-toast{position:fixed;top:20px;right:20px;z-index:999}.toast-popup{padding:12px 16px;border-radius:12px;font-weight:500;animation:slideIn .3s ease;box-shadow:0 10px 25px #0000004d}.toast-popup.success{background:#22c55e}.toast-popup.error{background:#ef4444}.toast-popup.warning{background:#f59e0b}.toast-popup.info{background:#3b82f6}@keyframes slideIn{0%{transform:translate(120%);opacity:0}to{transform:translate(0);opacity:1}}.receiver-card{background:#ffffff0d;border:1px solid rgba(255,255,255,.08);border-radius:16px;padding:20px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 15px 40px #0006}.title{font-size:22px;font-weight:600}.subtitle{font-size:14px;opacity:.7;margin-bottom:16px}.section{margin-top:10px}.section-title{margin-bottom:12px;font-size:16px;font-weight:600}.alert-title{color:#f87171}.toast-title{color:#fbbf24}.inapp-title{color:#60a5fa}.notification-card{padding:14px;border-radius:14px;margin-bottom:12px;border:1px solid rgba(255,255,255,.08);background:#ffffff0a;transition:.2s ease}.notification-card:hover{transform:scale(1.02);background:#ffffff12}.notification-card.alert{border-left:4px solid #ef4444}.notification-card.toast{border-left:4px solid #f59e0b}.notification-card.inapp{border-left:4px solid #3b82f6}.top-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.badge{font-size:11px;padding:3px 8px;border-radius:999px;background:#ffffff1a;letter-spacing:.5px}.time{font-size:11px;opacity:.6}.message{font-size:14px;line-height:1.4;opacity:.9}.toast-success{background:#22c55e;color:#fff}.toast-error{background:#ef4444;color:#fff}.toast-warning{background:#f59e0b;color:#fff}.toast-info{background:#3b82f6;color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2$1.DatePipe, name: "date" }] });
|
|
283
|
+
}
|
|
284
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: ReceiverComponent, decorators: [{
|
|
285
|
+
type: Component,
|
|
286
|
+
args: [{ selector: 'lib-receiver', standalone: true, imports: [CommonModule], template: "<div class=\"receiver-container\">\n\n <!-- BUTTONS -->\n <div class=\"btn-group\">\n\n <button \n [class.active]=\"activeTab === 'alert'\" \n (click)=\"activeTab = 'alert'; markTabAsRead('alert')\">Show Alerts\n <span class=\"badge-count\"\n *ngIf=\"alerts.filter(n => !n.isRead).length > 0\">\n {{ alerts.filter(n => !n.isRead).length }}\n </span>\n </button>\n\n <button \n [class.active]=\"activeTab === 'toast'\" \n (click)=\"activeTab = 'toast'; markTabAsRead('toast')\">Show Toast\n <span class=\"badge-count\"\n *ngIf=\"toasts.filter(n => !n.isRead).length > 0\">\n {{ toasts.filter(n => !n.isRead).length }}\n </span>\n </button>\n\n <button \n [class.active]=\"activeTab === 'inapp'\" \n (click)=\"activeTab = 'inapp'; markTabAsRead('inapp')\">Show Notifications\n <span class=\"badge-count\"\n *ngIf=\"inapps.filter(n => !n.isRead).length > 0\">\n {{ inapps.filter(n => !n.isRead).length }}\n </span>\n\n </button>\n\n </div>\n\n <!-- LIVE TOAST -->\n <div class=\"live-toast\" *ngIf=\"showToast\">\n <div class=\"toast-popup\" [class]=\"toastClass\">\n \uD83C\uDF5E {{ liveToastMessage }}\n </div>\n </div>\n\n <div class=\"receiver-card\">\n\n <h2 class=\"title\">\uD83D\uDCE5 Receiver Panel</h2>\n <p class=\"subtitle\">Live incoming notifications</p>\n\n <!-- ALERT -->\n <div class=\"section\" *ngIf=\"activeTab === 'alert'\">\n <h3 class=\"section-title alert-title\">\uD83D\uDEA8 Alerts</h3>\n\n <div *ngFor=\"let n of alerts\">\n <div class=\"notification-card alert\">\n <div class=\"top-row\">\n <div class=\"badge\">ALERT</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n <!-- TOAST -->\n <div class=\"section\" *ngIf=\"activeTab === 'toast'\">\n <h3 class=\"section-title toast-title\">\uD83C\uDF5E Toast</h3>\n\n <div *ngFor=\"let n of toasts\">\n <div class=\"notification-card toast\">\n <div class=\"top-row\">\n <div class=\"badge\">TOAST</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n <!-- INAPP -->\n <div class=\"section\" *ngIf=\"activeTab === 'inapp'\">\n <h3 class=\"section-title inapp-title\">\uD83D\uDD14 In-App Notifications</h3>\n\n <div *ngFor=\"let n of inapps\">\n <div class=\"notification-card inapp\">\n <div class=\"top-row\">\n <div class=\"badge\">IN-APP</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n </div>\n</div>", styles: [".receiver-container{min-height:100vh;padding:24px;font-family:system-ui,sans-serif;transition:background .3s ease,color .3s ease}.light-theme{background:#f5f7fb;color:#111827}.light-theme .receiver-card{background:#fff;border:1px solid #e5e7eb;color:#111827}.light-theme .btn-group{background:#fff;border:1px solid #e5e7eb}.light-theme .btn-group button{color:#111827;background:transparent}.light-theme .btn-group button:hover{background:#f3f4f6}.light-theme .btn-group button.active{background:#2563eb;color:#fff}.light-theme .notification-card{background:#fff;border:1px solid #e5e7eb;color:#111827}.light-theme .message,.light-theme .time,.light-theme .subtitle{color:#111827}.dark-theme{background:#0b1220;color:#f9fafb}.dark-theme .receiver-card{background:#111827;border:1px solid #1f2937;color:#f9fafb}.dark-theme .btn-group{background:#111827;border:1px solid #1f2937}.dark-theme .btn-group button{color:#d1d5db;background:transparent}.dark-theme .btn-group button:hover{background:#1f2937}.dark-theme .btn-group button.active{background:#3b82f6;color:#fff}.dark-theme .notification-card{background:#0f172a;border:1px solid #1f2937;color:#f9fafb}.dark-theme .message,.dark-theme .time,.dark-theme .subtitle{color:#f9fafb}.btn-group{display:flex;gap:12px;padding:10px;border-radius:12px;width:fit-content;margin:0 auto 20px}.btn-group button{position:relative;border:none;padding:10px 16px;border-radius:10px;cursor:pointer;font-weight:600;transition:all .2s ease}.badge-count{position:absolute;top:-6px;right:-6px;background:#ef4444;color:#fff;font-size:11px;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center}.receiver-card{max-width:900px;margin:auto;padding:20px;border-radius:14px}.notification-card{padding:14px;border-radius:10px;margin-bottom:12px;transition:transform .2s ease}.notification-card:hover{transform:translateY(-2px)}.message{font-size:14px;line-height:1.5;word-break:break-word}.time{font-size:12px}.receiver-card{max-width:900px;margin:auto;padding:22px;border-radius:16px;transition:all .3s ease;background:#ffffff05;box-shadow:0 10px 25px #00000040,0 0 0 1px #ffffff0a,0 0 40px #3b82f626}.receiver-card:hover{transform:translateY(-3px);box-shadow:0 15px 35px #00000059,0 0 0 1px #ffffff0f,0 0 60px #6366f140}.dark-theme .receiver-card{background:#0f172a;box-shadow:0 15px 40px #0009,0 0 0 1px #ffffff0d,0 0 50px #3b82f633}.light-theme .receiver-card{background:#fff;box-shadow:0 10px 25px #00000014,0 0 0 1px #0000000d,0 0 30px #3b82f614}.notification-card.alert{border-left:4px solid #ef4444;background:#ef44440f;box-shadow:0 8px 20px #00000040,0 0 0 1px #ef444426,0 0 25px #ef444440}.notification-card.alert:hover{transform:translateY(-3px);box-shadow:0 12px 30px #00000059,0 0 0 1px #ef444440,0 0 40px #ef444466}.notification-card.toast{border-left:4px solid #f59e0b;background:#f59e0b0f;box-shadow:0 8px 20px #00000038,0 0 0 1px #f59e0b2e,0 0 25px #f59e0b38}.notification-card.toast:hover{transform:translateY(-3px);box-shadow:0 12px 30px #0000004d,0 0 0 1px #f59e0b4d,0 0 40px #f59e0b59}.notification-card.inapp{border-left:4px solid #3b82f6;background:#3b82f60f;box-shadow:0 8px 20px #00000038,0 0 0 1px #3b82f62e,0 0 25px #3b82f638}.notification-card.inapp:hover{transform:translateY(-3px);box-shadow:0 12px 30px #0000004d,0 0 0 1px #3b82f64d,0 0 40px #3b82f659}.receiver-container{padding:20px;min-height:100vh;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.btn-group{display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap}.btn-group button{position:relative;padding:10px 16px;border-radius:12px;border:1px solid rgba(255,255,255,.1);background:#ffffff0f;cursor:pointer;transition:.25s ease;font-weight:500;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.btn-group button:hover{transform:translateY(-2px);background:#ffffff1a}.btn-group button.active{background:linear-gradient(135deg,#6366f1,#3b82f6);border:none;box-shadow:0 10px 25px #3b82f64d}.badge-count{margin-left:8px;background:#ef4444;color:#fff;font-size:12px;padding:2px 7px;border-radius:999px;position:absolute;top:-6px;right:-6px;box-shadow:0 4px 10px #0000004d}.live-toast{position:fixed;top:20px;right:20px;z-index:999}.toast-popup{padding:12px 16px;border-radius:12px;font-weight:500;animation:slideIn .3s ease;box-shadow:0 10px 25px #0000004d}.toast-popup.success{background:#22c55e}.toast-popup.error{background:#ef4444}.toast-popup.warning{background:#f59e0b}.toast-popup.info{background:#3b82f6}@keyframes slideIn{0%{transform:translate(120%);opacity:0}to{transform:translate(0);opacity:1}}.receiver-card{background:#ffffff0d;border:1px solid rgba(255,255,255,.08);border-radius:16px;padding:20px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 15px 40px #0006}.title{font-size:22px;font-weight:600}.subtitle{font-size:14px;opacity:.7;margin-bottom:16px}.section{margin-top:10px}.section-title{margin-bottom:12px;font-size:16px;font-weight:600}.alert-title{color:#f87171}.toast-title{color:#fbbf24}.inapp-title{color:#60a5fa}.notification-card{padding:14px;border-radius:14px;margin-bottom:12px;border:1px solid rgba(255,255,255,.08);background:#ffffff0a;transition:.2s ease}.notification-card:hover{transform:scale(1.02);background:#ffffff12}.notification-card.alert{border-left:4px solid #ef4444}.notification-card.toast{border-left:4px solid #f59e0b}.notification-card.inapp{border-left:4px solid #3b82f6}.top-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.badge{font-size:11px;padding:3px 8px;border-radius:999px;background:#ffffff1a;letter-spacing:.5px}.time{font-size:11px;opacity:.6}.message{font-size:14px;line-height:1.4;opacity:.9}.toast-success{background:#22c55e;color:#fff}.toast-error{background:#ef4444;color:#fff}.toast-warning{background:#f59e0b;color:#fff}.toast-info{background:#3b82f6;color:#fff}\n"] }]
|
|
287
|
+
}], ctorParameters: () => [{ type: Notification }, { type: i0.ChangeDetectorRef }, { type: Object, decorators: [{
|
|
288
|
+
type: Inject,
|
|
289
|
+
args: [PLATFORM_ID]
|
|
290
|
+
}] }] });
|
|
16
291
|
|
|
17
292
|
/**
|
|
18
293
|
* Generated bundle index. Do not edit.
|
|
19
294
|
*/
|
|
20
295
|
|
|
21
|
-
export {
|
|
296
|
+
export { Notification, ReceiverComponent, Sender };
|
|
22
297
|
//# sourceMappingURL=adarshctas-live-notification.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adarshctas-live-notification.mjs","sources":["../../../projects/live-notification/src/lib/live-notification.ts","../../../projects/live-notification/src/public-api.ts","../../../projects/live-notification/src/adarshctas-live-notification.ts"],"sourcesContent":["import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-live-notification',\n imports: [],\n template: ` <p>live-notification works!</p> `,\n styles: ``,\n})\nexport class LiveNotification {}\n","/*\n * Public API Surface of live-notification\n */\n\nexport * from './lib/live-notification';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;MAQa,gBAAgB,CAAA;wGAAhB,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,gBAAgB,iFAHjB,CAAA,iCAAA,CAAmC,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;4FAGlC,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAN5B,SAAS;+BACE,uBAAuB,EAAA,OAAA,EACxB,EAAE,EAAA,QAAA,EACD,CAAA,iCAAA,CAAmC,EAAA;;;ACL/C;;AAEG;;ACFH;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"adarshctas-live-notification.mjs","sources":["../../../projects/live-notification/src/lib/services/notification.ts","../../../projects/live-notification/src/lib/sender/sender.ts","../../../projects/live-notification/src/lib/sender/sender.html","../../../projects/live-notification/src/lib/receiver/receiver.ts","../../../projects/live-notification/src/lib/receiver/receiver.html","../../../projects/live-notification/src/adarshctas-live-notification.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { Observable,Subject } from 'rxjs';\nimport { io, Socket } from 'socket.io-client';\n\nexport type ToastType = 'success' | 'error' | 'warning' | 'info';\n\nexport interface Toast {\n message: string;\n type: ToastType;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class Notification {\n\n private receiver?: { setActiveType: (type: 'alert' | 'toast' | 'inapp') => void };\n\n /** Used by receiver component to expose a callback for sender actions. */\n registerReceiver(receiver: { setActiveType: (type: 'alert' | 'toast' | 'inapp') => void }) {\n this.receiver = receiver;\n }\n\n setActiveType(type: 'alert' | 'toast' | 'inapp') {\n this.receiver?.setActiveType(type);\n }\n\n private static socketInstance: Socket;\nprivate socket: Socket;\n\n // BASE URL\n private apiUrl = 'http://localhost:3000/api/notifications';\n\n constructor(private http: HttpClient) { if (!Notification.socketInstance) {\n Notification.socketInstance = io('http://localhost:3000');\n }\n\n this.socket = Notification.socketInstance; }\n\n // SEND NOTIFICATION\n sendNotification(data: any): Observable<any> {\n\n return this.http.post(\n `${this.apiUrl}/send`,\n data\n );\n\n }\n\n // GET ALL NOTIFICATIONS\n getAll(): Observable<any> {\n\n return this.http.get(\n `${this.apiUrl}/all`\n );\n\n }\n\n // REALTIME LISTENER\nlistenNotification(): Observable<any> {\n return new Observable((observer) => {\n\n const handler = (data: any) => observer.next(data);\n\n this.socket.on('notification', handler);\n\n return () => {\n this.socket.off('notification', handler);\n };\n\n });\n}\n\n listenNotificationByType(type: string): Observable<any> {\n return new Observable((observer) => {\n const eventName = `notification:${type}`;\n const handler = (data: any) => observer.next(data);\n\n this.socket.on(eventName, handler);\n\n return () => {\n this.socket.off(eventName, handler);\n };\n });\n }\n // MARK AS READ\n markAsRead(id: string): Observable<any> {\n return this.http.put(\n `${this.apiUrl}/read/${id}`,\n { isRead: true }\n );\n }\n private toastSubject = new Subject<Toast>();\ntoast$ = this.toastSubject.asObservable();\n\nprivate emitToast(message: string, type: ToastType) {\n this.toastSubject.next({ message, type });\n}\n\nsuccess(msg: string) {\n this.emitToast(msg, 'success');\n}\n\nerror(msg: string) {\n this.emitToast(msg, 'error');\n}\n\nwarning(msg: string) {\n this.emitToast(msg, 'warning');\n}\n\ninfo(msg: string) {\n this.emitToast(msg, 'info');\n}\n\ndisconnectSocket() {\n if (this.socket) {\n this.socket.disconnect();\n }\n}\n} \n","import { Component, ChangeDetectorRef } from '@angular/core';\nimport { Notification } from '../services/notification';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\n@Component({\n selector: 'app-sender',\n imports: [CommonModule, FormsModule],\n templateUrl: './sender.html',\n styleUrl: './sender.css',\n})\nexport class Sender {\n\n message = '';\n\n constructor(\n private notificationService: Notification,\n private cd: ChangeDetectorRef\n ) {}\n\nsend(type: string, level: string = 'INFO') {\n\n if (!this.message.trim()) {\n return;\n }\n\n const payload = {\n type:type,\n level: level,\n message: this.message,\n userId: 'global'\n };\n\n\n // No realtime updates while typing.\n // Receiver will only update the selected section based on button click.\n (this.notificationService as any).setActiveType?.(type);\n\n\n this.notificationService.sendNotification(payload).subscribe({\n\n next: () => {\n this.message = '';\n\n },\n\n error: (err) => {\n console.error('Notification send error:', err);\n\n }\n });\n\n }\n \n}","<div class=\"sender-container\">\n\n \n <div class=\"card\">\n \n <h2 class=\"title\">📤 Sender Panel</h2>\n\n <p class=\"subtitle\">\n Send real-time notifications instantly\n </p>\n\n <!-- Input -->\n <div class=\"input-box\">\n\n <input\n type=\"text\"\n placeholder=\"Enter notification message...\"\n [(ngModel)]=\"message\"\n (keydown.enter)=\"$event.preventDefault()\"\n />\n\n </div>\n\n <!-- Buttons -->\n <div class=\"btn-group\">\n\n <button\n type=\"button\"\n class=\"alert-btn\"\n (click)=\"send('alert')\"\n [disabled]=\"!message.trim()\"\n >\n 🚨 Send Alert\n </button>\n\n <button\n type=\"button\"\n class=\"toast-btn\"\n (click)=\"send('toast')\"\n [disabled]=\"!message.trim()\"\n >\n 🍞 Send Toast\n </button>\n<div class=\"btn\">\n <button (click)=\"send('toast', 'SUCCESS')\">Success</button>\n <button (click)=\"send('toast', 'ERROR')\">Error</button>\n <button (click)=\"send('toast', 'WARNING')\">Warning</button>\n <button (click)=\"send('toast', 'INFO')\">Info</button>\n</div>\n <button\n type=\"button\"\n class=\"inapp-btn\"\n (click)=\"send('inapp')\"\n [disabled]=\"!message.trim()\"\n >\n 🔔 Send In-App\n </button>\n\n </div>\n\n </div>\n\n</div>","import {\n Component,\n OnInit,\n OnDestroy,\n AfterViewInit,\n ChangeDetectorRef,\n Inject,\n PLATFORM_ID,\n \n} from '@angular/core';\n\nimport { CommonModule, isPlatformBrowser } from '@angular/common';\nimport { Notification } from '../services/notification';\nimport { interval, Subscription } from 'rxjs';\n\n@Component({\n selector: 'lib-receiver',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './receiver.html',\n styleUrl: './receiver.css',\n})\nexport class ReceiverComponent implements OnInit, OnDestroy, AfterViewInit {\n\n alerts: any[] = [];\n toasts: any[] = [];\n inapps: any[] = [];\n\n showToast = false;\n liveToastMessage = '';\n toastClass = 'toast-info';\n\nactiveTab: 'alert' | 'toast' | 'inapp' | null = null;\n\n private refreshSub?: Subscription;\n private toastSub?: Subscription;\n private inappSub?: Subscription;\n private alertSub?: Subscription;\n\n constructor(\n private notificationService: Notification,\n private cd: ChangeDetectorRef,\n @Inject(PLATFORM_ID) private platformId: Object\n ) {}\n\n // =========================\n // INIT\n // =========================\n ngOnInit(): void {\n this.notificationService.registerReceiver(this);\n this.loadData();\n\n this.refreshSub = interval(3000).subscribe(() => {\n this.loadData();\n });\n }\n\n setActiveType(type: 'alert' | 'toast' | 'inapp'): void {\n this.activeTab = type;\n this.markTabAsRead(type);\n this.cd.detectChanges();\n }\n\n // =========================\n // LOAD ALL DATA\n // =========================\n loadData(): void {\n this.notificationService.getAll().subscribe({\n next: (res: any) => {\n const data = res.data || [];\n\n this.alerts = data.filter((n: any) => n.type === 'alert');\n this.toasts = data.filter((n: any) => n.type === 'toast');\n this.inapps = data.filter((n: any) => n.type === 'inapp');\n\n this.cd.detectChanges();\n },\n error: (err: any) => {\n console.error('Load notification error:', err);\n }\n });\n }\n\n // =========================\n // AFTER VIEW (REALTIME)\n // =========================\n ngAfterViewInit(): void {\n if (!isPlatformBrowser(this.platformId)) return;\n\n if ('Notification' in window) {\n window.Notification.requestPermission();\n }\n\n // ALERT\n this.alertSub = this.notificationService\n .listenNotificationByType('alert')\n .subscribe((data: any) => {\n if (!this.alerts.find(n => n._id === data._id)) {\n this.alerts.unshift(data);\n }\n\n alert(`🚨 ALERT\\n\\n${data.message}`);\n this.cd.detectChanges();\n });\n\n // TOAST\n this.toastSub = this.notificationService\n .listenNotificationByType('toast')\n .subscribe((data: any) => {\n\n if (!this.toasts.find(n => n._id === data._id)) {\n this.toasts.unshift(data);\n }\n\n this.liveToastMessage = data.message;\n this.toastClass = this.getToastClass(data.level);\n this.showToast = true;\n\n setTimeout(() => {\n this.showToast = false;\n this.cd.detectChanges();\n }, 3000);\n\n this.cd.detectChanges();\n });\n\n // INAPP\n this.inappSub = this.notificationService\n .listenNotificationByType('inapp')\n .subscribe((data: any) => {\n\n this.inapps.unshift(data);\n\n if (\n 'Notification' in window &&\n window.Notification.permission === 'granted'\n ) {\n new window.Notification('🔔 New Notification', {\n body: data.message,\n });\n }\n\n this.cd.detectChanges();\n });\n }\n\n // =========================\n // MARK AS READ (IMPORTANT)\n // =========================\n markTabAsRead(type: string): void {\n let list: any[] = [];\n\n if (type === 'alert') list = this.alerts;\n if (type === 'toast') list = this.toasts;\n if (type === 'inapp') list = this.inapps;\n\n list.forEach(n => {\n if (!n.isRead) {\n n.isRead = true;\n\n // backend update (optional)\n this.notificationService.markAsRead(n._id).subscribe({\n error: (err: any) => console.error(err)\n });\n }\n });\n\n this.cd.detectChanges();\n }\n\n // =========================\n // CLEANUP\n // =========================\nngOnDestroy(): void {\n this.alertSub?.unsubscribe();\n this.toastSub?.unsubscribe();\n this.inappSub?.unsubscribe();\n this.refreshSub?.unsubscribe();\n\n this.notificationService.disconnectSocket?.();\n}\n\ngetToastClass(level: string) {\n switch (level) {\n\n case 'SUCCESS':\n return 'toast-success';\n\n case 'ERROR':\n return 'toast-error';\n\n case 'WARNING':\n return 'toast-warning';\n\n case 'INFO':\n return 'toast-info';\n\n default:\n return 'toast-info';\n }\n}\n\n}","<div class=\"receiver-container\">\n\n <!-- BUTTONS -->\n <div class=\"btn-group\">\n\n <button \n [class.active]=\"activeTab === 'alert'\" \n (click)=\"activeTab = 'alert'; markTabAsRead('alert')\">Show Alerts\n <span class=\"badge-count\"\n *ngIf=\"alerts.filter(n => !n.isRead).length > 0\">\n {{ alerts.filter(n => !n.isRead).length }}\n </span>\n </button>\n\n <button \n [class.active]=\"activeTab === 'toast'\" \n (click)=\"activeTab = 'toast'; markTabAsRead('toast')\">Show Toast\n <span class=\"badge-count\"\n *ngIf=\"toasts.filter(n => !n.isRead).length > 0\">\n {{ toasts.filter(n => !n.isRead).length }}\n </span>\n </button>\n\n <button \n [class.active]=\"activeTab === 'inapp'\" \n (click)=\"activeTab = 'inapp'; markTabAsRead('inapp')\">Show Notifications\n <span class=\"badge-count\"\n *ngIf=\"inapps.filter(n => !n.isRead).length > 0\">\n {{ inapps.filter(n => !n.isRead).length }}\n </span>\n\n </button>\n\n </div>\n\n <!-- LIVE TOAST -->\n <div class=\"live-toast\" *ngIf=\"showToast\">\n <div class=\"toast-popup\" [class]=\"toastClass\">\n 🍞 {{ liveToastMessage }}\n </div>\n </div>\n\n <div class=\"receiver-card\">\n\n <h2 class=\"title\">📥 Receiver Panel</h2>\n <p class=\"subtitle\">Live incoming notifications</p>\n\n <!-- ALERT -->\n <div class=\"section\" *ngIf=\"activeTab === 'alert'\">\n <h3 class=\"section-title alert-title\">🚨 Alerts</h3>\n\n <div *ngFor=\"let n of alerts\">\n <div class=\"notification-card alert\">\n <div class=\"top-row\">\n <div class=\"badge\">ALERT</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n <!-- TOAST -->\n <div class=\"section\" *ngIf=\"activeTab === 'toast'\">\n <h3 class=\"section-title toast-title\">🍞 Toast</h3>\n\n <div *ngFor=\"let n of toasts\">\n <div class=\"notification-card toast\">\n <div class=\"top-row\">\n <div class=\"badge\">TOAST</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n <!-- INAPP -->\n <div class=\"section\" *ngIf=\"activeTab === 'inapp'\">\n <h3 class=\"section-title inapp-title\">🔔 In-App Notifications</h3>\n\n <div *ngFor=\"let n of inapps\">\n <div class=\"notification-card inapp\">\n <div class=\"top-row\">\n <div class=\"badge\">IN-APP</div>\n <small class=\"time\">{{ n.createdAt | date:'short' }}</small>\n </div>\n <p class=\"message\">{{ n.message }}</p>\n </div>\n </div>\n </div>\n\n </div>\n</div>","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.Notification","i2"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,78 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
1
3
|
import * as i0 from '@angular/core';
|
|
4
|
+
import { ChangeDetectorRef, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
type ToastType = 'success' | 'error' | 'warning' | 'info';
|
|
7
|
+
interface Toast {
|
|
8
|
+
message: string;
|
|
9
|
+
type: ToastType;
|
|
10
|
+
}
|
|
11
|
+
declare class Notification {
|
|
12
|
+
private http;
|
|
13
|
+
private receiver?;
|
|
14
|
+
/** Used by receiver component to expose a callback for sender actions. */
|
|
15
|
+
registerReceiver(receiver: {
|
|
16
|
+
setActiveType: (type: 'alert' | 'toast' | 'inapp') => void;
|
|
17
|
+
}): void;
|
|
18
|
+
setActiveType(type: 'alert' | 'toast' | 'inapp'): void;
|
|
19
|
+
private static socketInstance;
|
|
20
|
+
private socket;
|
|
21
|
+
private apiUrl;
|
|
22
|
+
constructor(http: HttpClient);
|
|
23
|
+
sendNotification(data: any): Observable<any>;
|
|
24
|
+
getAll(): Observable<any>;
|
|
25
|
+
listenNotification(): Observable<any>;
|
|
26
|
+
listenNotificationByType(type: string): Observable<any>;
|
|
27
|
+
markAsRead(id: string): Observable<any>;
|
|
28
|
+
private toastSubject;
|
|
29
|
+
toast$: Observable<Toast>;
|
|
30
|
+
private emitToast;
|
|
31
|
+
success(msg: string): void;
|
|
32
|
+
error(msg: string): void;
|
|
33
|
+
warning(msg: string): void;
|
|
34
|
+
info(msg: string): void;
|
|
35
|
+
disconnectSocket(): void;
|
|
36
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<Notification, never>;
|
|
37
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<Notification>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare class Sender {
|
|
41
|
+
private notificationService;
|
|
42
|
+
private cd;
|
|
43
|
+
message: string;
|
|
44
|
+
constructor(notificationService: Notification, cd: ChangeDetectorRef);
|
|
45
|
+
send(type: string, level?: string): void;
|
|
46
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<Sender, never>;
|
|
47
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<Sender, "app-sender", never, {}, {}, never, never, true, never>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
declare class ReceiverComponent implements OnInit, OnDestroy, AfterViewInit {
|
|
51
|
+
private notificationService;
|
|
52
|
+
private cd;
|
|
53
|
+
private platformId;
|
|
54
|
+
alerts: any[];
|
|
55
|
+
toasts: any[];
|
|
56
|
+
inapps: any[];
|
|
57
|
+
showToast: boolean;
|
|
58
|
+
liveToastMessage: string;
|
|
59
|
+
toastClass: string;
|
|
60
|
+
activeTab: 'alert' | 'toast' | 'inapp' | null;
|
|
61
|
+
private refreshSub?;
|
|
62
|
+
private toastSub?;
|
|
63
|
+
private inappSub?;
|
|
64
|
+
private alertSub?;
|
|
65
|
+
constructor(notificationService: Notification, cd: ChangeDetectorRef, platformId: Object);
|
|
66
|
+
ngOnInit(): void;
|
|
67
|
+
setActiveType(type: 'alert' | 'toast' | 'inapp'): void;
|
|
68
|
+
loadData(): void;
|
|
69
|
+
ngAfterViewInit(): void;
|
|
70
|
+
markTabAsRead(type: string): void;
|
|
71
|
+
ngOnDestroy(): void;
|
|
72
|
+
getToastClass(level: string): "toast-info" | "toast-success" | "toast-error" | "toast-warning";
|
|
73
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ReceiverComponent, never>;
|
|
74
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ReceiverComponent, "lib-receiver", never, {}, {}, never, never, true, never>;
|
|
6
75
|
}
|
|
7
76
|
|
|
8
|
-
export {
|
|
77
|
+
export { Notification, ReceiverComponent, Sender };
|
|
78
|
+
export type { Toast, ToastType };
|