diff --git a/config/routes/notification.yaml b/config/routes/notification.yaml new file mode 100644 index 00000000..7bb58aa7 --- /dev/null +++ b/config/routes/notification.yaml @@ -0,0 +1,4 @@ +notification_ajax_list: + path: /ajax/notifications + controller: App\Controller\NotificationController::ajaxList + methods: [GET] diff --git a/config/services.yaml b/config/services.yaml index 3d9fd7a3..7d585e08 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -221,6 +221,12 @@ services: event: 'postPersist' entity: 'App\Entity\JobOrder' + App\Service\NotificationManager: + arguments: + $redis_prov: "@App\\Service\\RedisClientProvider" + $redis_mqtt_key: "mqtt_events" + $em: "@doctrine.orm.entity_manager" + App\Service\JobOrderCache: arguments: $redis_prov: "@App\\Service\\RedisClientProvider" diff --git a/public/assets/js/notification.js b/public/assets/js/notification.js new file mode 100644 index 00000000..bc1bfc40 --- /dev/null +++ b/public/assets/js/notification.js @@ -0,0 +1,95 @@ +class NotificationHandler { + constructor(options) { + this.options = options; + } + + clearAll() { + // clear notification count + document.getElementById('notif-count').innerHTML = ''; + + // remove notifications + document.getElementById('notif-body').innerHTML = ''; + } + + loadAll() { + console.log('loading notifications'); + // ajax load + var self = this; + var xhr = new XMLHttpRequest(); + xhr.open('GET', this.options['notif_ajax_url']); + xhr.onload = function() { + if (xhr.status === 200) { + var data = JSON.parse(xhr.responseText); + var notifs = data.notifications; + + // update notification count + var count_html = data.count; + document.getElementById('notif-count').innerHTML = count_html; + + // do we have any notifications? + if (notifs.length <= 0) + return; + + // add actual notifications + var notif_body = document.getElementById('notif-body'); + notifs.forEach(function(notif) { + var notif_date = moment(notif.date).fromNow(); + + var notif_html = '
'; + notif_html += ''; + notif_html += ''; + notif_html += '' + notif.text + ''; + notif_html += ''; + notif_html += ''; + notif_html += notif_date; + notif_html += ''; + notif_html += '
'; + + notif_body.insertAdjacentHTML('beforeend', notif_html); + }); + } + + }; + xhr.send(); + } + + listen(user_id, host, port, use_ssl = false) { + var d = new Date(); + var client_id = "dash-" + user_id + "-" + d.getMonth() + "-" + d.getDate() + "-" + d.getHours() + "-" + d.getMinutes() + "-" + d.getSeconds() + "-" + d.getMilliseconds(); + + this.mqtt = new Paho.MQTT.Client(host, port, client_id); + var options = { + useSSL: use_ssl, + timeout: 3, + invocationContext: this, + onSuccess: this.onConnect.bind(this) + } + + this.mqtt.onMessageArrived = this.onMessage.bind(this); + + this.mqtt.connect(options); + } + + onConnect(icontext) { + console.log('notification mqtt connected'); + var my = icontext.invocationContext; + + // subscribe to general notifications + my.mqtt.subscribe('user/0/notification'); + } + + onMessage(msg) { + console.log('notification event received'); + // we don't care about messasge, we update + this.clearAll(); + this.loadAll(); + } + + getIcon(type_id) { + if (type_id in this.options['icons']) { + return this.options['icons'][type_id]; + } + + return this.options['default_icon']; + } +} diff --git a/src/Controller/NotificationController.php b/src/Controller/NotificationController.php new file mode 100644 index 00000000..54928528 --- /dev/null +++ b/src/Controller/NotificationController.php @@ -0,0 +1,80 @@ +sub(new DateInterval('PT10M')); + $notifs = [ + [ + 'id' => 1, + 'type' => 'jo_new', + 'date' => $date->format('Y-m-d\TH:i:s.000P'), + 'text' => 'Sample incoming job order', + 'link' => '#', + ], [ + 'id' => 2, + 'type' => 'rider_accept', + 'date' => $date->format('Y-m-d\TH:i:s.000P'), + 'text' => 'Sample rider has accepted job order', + 'link' => '#', + ], [ + 'id' => 3, + 'type' => 'jo_cancel', + 'date' => $date->format('Y-m-d\TH:i:s.000P'), + 'text' => 'Customer has cancelled job order.', + 'link' => '#', + ], [ + 'id' => 3, + 'type' => 'rider_reject', + 'date' => $date->format('Y-m-d\TH:i:s.000P'), + 'text' => 'Rider has rejected job order. Job order needs to be reassigned.', + 'link' => '#', + ], + ]; + $sample_data = [ + 'count' => 4, + 'notifications' => $notifs, + ]; + */ + + $notifs = $em->getRepository(Notification::class)->findBy(['user_id' => 0]); + $notif_data = []; + + foreach ($notifs as $notif) + { + $notif_data[] = [ + 'id' => $notif->getID(), + 'type' => 'jo_new', + 'date' => $notif->getDateCreate()->format('Y-m-d\TH:i:s.000P'), + 'text' => $notif->getMessage(), + 'link' => $notif->getURL(), + ]; + } + + + $sample_data = [ + 'count' => count($notif_data), + 'notifications' => $notif_data, + ]; + + $res = new JsonResponse($sample_data); + + return $res; + } +} diff --git a/src/Entity/Notification.php b/src/Entity/Notification.php new file mode 100644 index 00000000..c702ce25 --- /dev/null +++ b/src/Entity/Notification.php @@ -0,0 +1,139 @@ +id; + } + + public function getDateCreate() + { + return $this->date_create; + } + + public function setUserID($user_id) + { + $this->user_id = $user_id; + return $this; + } + + public function getUserID() + { + return $this->user_id; + } + + public function setIcon($icon) + { + $this->icon = $icon; + return $this; + } + + public function getIcon() + { + return $this->icon; + } + + public function setMessage($message) + { + $this->message = $message; + return $this; + } + + public function getMessage() + { + return $this->message; + } + + public function setURL($url) + { + $this->url = $url; + return $this; + } + + public function getURL() + { + return $this->url; + } + + public function setIsRead($bool = true) + { + $this->flag_read = $bool; + return $this; + } + + public function isRead() + { + return $this->flag_read; + } + + public function setIsFresh($bool = true) + { + $this->flag_fresh = $bool; + return $this; + } + + public function isFresh() + { + return $this->flag_fresh; + } +} diff --git a/src/Service/NotificationManager.php b/src/Service/NotificationManager.php new file mode 100644 index 00000000..f0a6deec --- /dev/null +++ b/src/Service/NotificationManager.php @@ -0,0 +1,44 @@ +redis = $redis_prov->getRedisClient(); + $this->redis_mqtt_key = $redis_mqtt_key; + $this->em = $em; + } + + // set user_id to 0 for all + public function sendNotification($user_id, $msg) + { + // send mqtt + $chan = $this->getChannel($user_id); + $data = $chan . '|' . $msg; + $this->redis->lpush($this->redis_mqtt_key, $data); + + // create notif + $notif = new Notification(); + + // save to db + $this->em->persist($notif); + $this->em->flush(); + } + + protected function getChannel($user_id) + { + return str_replace('{user_id}', $user_id, self::NOTIF_KEY ); + } +} diff --git a/templates/base.html.twig b/templates/base.html.twig index 5e5abfc2..21438dca 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -448,217 +448,50 @@
+ + @@ -770,6 +605,25 @@ + + + + {% block scripts %}{% endblock %}