Add notification entity and service #472
This commit is contained in:
parent
4e6bc0d95f
commit
885665f9d3
7 changed files with 433 additions and 211 deletions
4
config/routes/notification.yaml
Normal file
4
config/routes/notification.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
notification_ajax_list:
|
||||||
|
path: /ajax/notifications
|
||||||
|
controller: App\Controller\NotificationController::ajaxList
|
||||||
|
methods: [GET]
|
||||||
|
|
@ -221,6 +221,12 @@ services:
|
||||||
event: 'postPersist'
|
event: 'postPersist'
|
||||||
entity: 'App\Entity\JobOrder'
|
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:
|
App\Service\JobOrderCache:
|
||||||
arguments:
|
arguments:
|
||||||
$redis_prov: "@App\\Service\\RedisClientProvider"
|
$redis_prov: "@App\\Service\\RedisClientProvider"
|
||||||
|
|
|
||||||
95
public/assets/js/notification.js
Normal file
95
public/assets/js/notification.js
Normal file
|
|
@ -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 = '<div class="m-list-timeline__item">';
|
||||||
|
notif_html += '<span class="m-list-timeline__badge -m-list-timeline__badge--state-success"></span>';
|
||||||
|
notif_html += '<span class="m-list-timeline__text">';
|
||||||
|
notif_html += '<a href="' + notif.link + '">' + notif.text + '</a>';
|
||||||
|
notif_html += '</span>';
|
||||||
|
notif_html += '<span class="m-list-timeline__time">';
|
||||||
|
notif_html += notif_date;
|
||||||
|
notif_html += '</span>';
|
||||||
|
notif_html += '</div>';
|
||||||
|
|
||||||
|
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'];
|
||||||
|
}
|
||||||
|
}
|
||||||
80
src/Controller/NotificationController.php
Normal file
80
src/Controller/NotificationController.php
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Catalyst\MenuBundle\Annotation\Menu;
|
||||||
|
use DateTime;
|
||||||
|
use DateInterval;
|
||||||
|
use App\Entity\Notification;
|
||||||
|
|
||||||
|
class NotificationController extends AbstractController
|
||||||
|
{
|
||||||
|
// TODO: security
|
||||||
|
public function ajaxList(EntityManagerInterface $em)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
$date = new DateTime();
|
||||||
|
$date->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
139
src/Entity/Notification.php
Normal file
139
src/Entity/Notification.php
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity
|
||||||
|
* @ORM\Table(name="notification", indexes={@ORM\Index(columns={"user_id"})})
|
||||||
|
*/
|
||||||
|
class Notification
|
||||||
|
{
|
||||||
|
// unique id
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
* @ORM\GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
// date / time created
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime")
|
||||||
|
*/
|
||||||
|
protected $date_create;
|
||||||
|
|
||||||
|
// index by user for fast fetching
|
||||||
|
// user id (don't link, don't need to)
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
protected $user_id;
|
||||||
|
|
||||||
|
// icon
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=25)
|
||||||
|
*/
|
||||||
|
protected $icon;
|
||||||
|
|
||||||
|
// message text
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=300)
|
||||||
|
*/
|
||||||
|
protected $message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=180)
|
||||||
|
*/
|
||||||
|
protected $url;
|
||||||
|
|
||||||
|
// has user read the notification
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="boolean")
|
||||||
|
*/
|
||||||
|
protected $flag_read;
|
||||||
|
|
||||||
|
// is this still a fresh notification for the user
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="boolean")
|
||||||
|
*/
|
||||||
|
protected $flag_fresh;
|
||||||
|
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return $this->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/Service/NotificationManager.php
Normal file
44
src/Service/NotificationManager.php
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use App\Service\RedisClientProvider;
|
||||||
|
use App\Entity\Notification;
|
||||||
|
|
||||||
|
class NotificationManager
|
||||||
|
{
|
||||||
|
protected $redis;
|
||||||
|
protected $redis_mqtt_key;
|
||||||
|
protected $em;
|
||||||
|
|
||||||
|
const NOTIF_KEY = 'user/{user_id}/notification';
|
||||||
|
|
||||||
|
public function __construct(RedisClientProvider $redis_prov, EntityManagerInterface $em, $redis_mqtt_key)
|
||||||
|
{
|
||||||
|
$this->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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -448,217 +448,50 @@
|
||||||
<div id="m_header_topbar" class="m-topbar m-stack m-stack--ver m-stack--general">
|
<div id="m_header_topbar" class="m-topbar m-stack m-stack--ver m-stack--general">
|
||||||
<div class="m-stack__item m-topbar__nav-wrapper">
|
<div class="m-stack__item m-topbar__nav-wrapper">
|
||||||
<ul class="m-topbar__nav m-nav m-nav--inline">
|
<ul class="m-topbar__nav m-nav m-nav--inline">
|
||||||
<!--
|
|
||||||
<li class="m-nav__item m-topbar__notifications m-topbar__notifications--img m-dropdown m-dropdown--large m-dropdown--header-bg-fill m-dropdown--arrow m-dropdown--align-center m-dropdown--mobile-full-width" data-dropdown-toggle="click" data-dropdown-persistent="true">
|
<li class="m-nav__item m-topbar__notifications m-topbar__notifications--img m-dropdown m-dropdown--large m-dropdown--header-bg-fill m-dropdown--arrow m-dropdown--align-right m-dropdown--mobile-full-width" data-dropdown-toggle="click" data-dropdown-persistent="true">
|
||||||
<a href="#" class="m-nav__link m-dropdown__toggle" id="m_topbar_notification_icon">
|
<a href="#" class="m-nav__link m-dropdown__toggle" id="m_topbar_notification_icon">
|
||||||
<span class="m-nav__link-badge m-badge m-badge--dot m-badge--dot-small m-badge--danger"></span>
|
<span class="m-nav__link-badge m-badge m-badge--dot m-badge--dot-small m-badge--danger"></span>
|
||||||
<span class="m-nav__link-icon">
|
<span class="m-nav__link-icon">
|
||||||
<i class="flaticon-music-2"></i>
|
<i class="flaticon-music-2"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="m-dropdown__wrapper">
|
<div class="m-dropdown__wrapper">
|
||||||
<span class="m-dropdown__arrow m-dropdown__arrow--center"></span>
|
<span class="m-dropdown__arrow m-dropdown__arrow--right m-dropdown__arrow--adjust"></span>
|
||||||
<div class="m-dropdown__inner">
|
<div class="m-dropdown__inner">
|
||||||
<div class="m-dropdown__header m--align-center" style="background: url(assets/app/media/img/misc/notification_bg.jpg); background-size: cover;">
|
<div class="m-dropdown__header m--align-center" style="background: url(assets/app/media/img/misc/notification_bg.jpg); background-size: cover;">
|
||||||
<span class="m-dropdown__header-title">
|
<span class="m-dropdown__header-title">
|
||||||
9 New
|
<span id="notif-count">-</span> New
|
||||||
</span>
|
</span>
|
||||||
<span class="m-dropdown__header-subtitle">
|
<span class="m-dropdown__header-subtitle">
|
||||||
User Notifications
|
User Notifications
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-dropdown__body">
|
<div class="m-dropdown__body">
|
||||||
<div class="m-dropdown__content">
|
<div class="m-dropdown__content">
|
||||||
<ul class="nav nav-tabs m-tabs m-tabs-line m-tabs-line--brand" role="tablist">
|
<div class="m-scrollable" data-scrollable="true" data-max-height="250" data-mobile-max-height="200">
|
||||||
<li class="nav-item m-tabs__item">
|
<div class="m-list-timeline m-list-timeline--skin-light">
|
||||||
<a class="nav-link m-tabs__link active" data-toggle="tab" href="#topbar_notifications_notifications" role="tab">
|
<div id="notif-body" class="m-list-timeline__items">
|
||||||
Alerts
|
<div class="m-list-timeline__item">
|
||||||
</a>
|
<span class="m-list-timeline__badge -m-list-timeline__badge--state-success"></span>
|
||||||
</li>
|
<span class="m-list-timeline__text">
|
||||||
<li class="nav-item m-tabs__item">
|
<a href="#">This is a notification</a>
|
||||||
<a class="nav-link m-tabs__link" data-toggle="tab" href="#topbar_notifications_events" role="tab">
|
</span>
|
||||||
Events
|
<span class="m-list-timeline__time">
|
||||||
</a>
|
Just now
|
||||||
</li>
|
</span>
|
||||||
<li class="nav-item m-tabs__item">
|
</div>
|
||||||
<a class="nav-link m-tabs__link" data-toggle="tab" href="#topbar_notifications_logs" role="tab">
|
</div>
|
||||||
Logs
|
</div>
|
||||||
</a>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
<div class="tab-content">
|
</div>
|
||||||
<div class="tab-pane active" id="topbar_notifications_notifications" role="tabpanel">
|
</div>
|
||||||
<div class="m-scrollable" data-scrollable="true" data-max-height="250" data-mobile-max-height="200">
|
</li>
|
||||||
<div class="m-list-timeline m-list-timeline--skin-light">
|
|
||||||
<div class="m-list-timeline__items">
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge -m-list-timeline__badge--state-success"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
12 new users registered
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
Just now
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
System shutdown
|
|
||||||
<span class="m-badge m-badge--success m-badge--wide">
|
|
||||||
pending
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
14 mins
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
New invoice received
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
20 mins
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
DB overloaded 80%
|
|
||||||
<span class="m-badge m-badge--info m-badge--wide">
|
|
||||||
settled
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
1 hr
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
System error -
|
|
||||||
<a href="#" class="m-link">
|
|
||||||
Check
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
2 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item m-list-timeline__item--read">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span href="" class="m-list-timeline__text">
|
|
||||||
New order received
|
|
||||||
<span class="m-badge m-badge--danger m-badge--wide">
|
|
||||||
urgent
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
7 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item m-list-timeline__item--read">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
Production server down
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
3 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge"></span>
|
|
||||||
<span class="m-list-timeline__text">
|
|
||||||
Production server up
|
|
||||||
</span>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
5 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane" id="topbar_notifications_events" role="tabpanel">
|
|
||||||
<div class="m-scrollable" m-scrollabledata-scrollable="true" data-max-height="250" data-mobile-max-height="200">
|
|
||||||
<div class="m-list-timeline m-list-timeline--skin-light">
|
|
||||||
<div class="m-list-timeline__items">
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge m-list-timeline__badge--state1-success"></span>
|
|
||||||
<a href="" class="m-list-timeline__text">
|
|
||||||
New order received
|
|
||||||
</a>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
Just now
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge m-list-timeline__badge--state1-danger"></span>
|
|
||||||
<a href="" class="m-list-timeline__text">
|
|
||||||
New invoice received
|
|
||||||
</a>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
20 mins
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge m-list-timeline__badge--state1-success"></span>
|
|
||||||
<a href="" class="m-list-timeline__text">
|
|
||||||
Production server up
|
|
||||||
</a>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
5 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge m-list-timeline__badge--state1-info"></span>
|
|
||||||
<a href="" class="m-list-timeline__text">
|
|
||||||
New order received
|
|
||||||
</a>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
7 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge m-list-timeline__badge--state1-info"></span>
|
|
||||||
<a href="" class="m-list-timeline__text">
|
|
||||||
System shutdown
|
|
||||||
</a>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
11 mins
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="m-list-timeline__item">
|
|
||||||
<span class="m-list-timeline__badge m-list-timeline__badge--state1-info"></span>
|
|
||||||
<a href="" class="m-list-timeline__text">
|
|
||||||
Production server down
|
|
||||||
</a>
|
|
||||||
<span class="m-list-timeline__time">
|
|
||||||
3 hrs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane" id="topbar_notifications_logs" role="tabpanel">
|
|
||||||
<div class="m-stack m-stack--ver m-stack--general" style="min-height: 180px;">
|
|
||||||
<div class="m-stack__item m-stack__item--center m-stack__item--middle">
|
|
||||||
<span class="">
|
|
||||||
All caught up!
|
|
||||||
<br>
|
|
||||||
No new logs.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
-->
|
|
||||||
<li class="m-nav__item m-topbar__user-profile m-topbar__user-profile--img m-dropdown m-dropdown--medium m-dropdown--arrow m-dropdown--header-bg-fill m-dropdown--align-right m-dropdown--mobile-full-width m-dropdown--skin-light" data-dropdown-toggle="click">
|
<li class="m-nav__item m-topbar__user-profile m-topbar__user-profile--img m-dropdown m-dropdown--medium m-dropdown--arrow m-dropdown--header-bg-fill m-dropdown--align-right m-dropdown--mobile-full-width m-dropdown--skin-light" data-dropdown-toggle="click">
|
||||||
<a href="#" class="m-nav__link m-dropdown__toggle">
|
<a href="#" class="m-nav__link m-dropdown__toggle">
|
||||||
<span class="m-topbar__userpic">
|
<span class="m-topbar__userpic">
|
||||||
|
|
@ -718,6 +551,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -770,6 +605,25 @@
|
||||||
<!--end::Page Snippets -->
|
<!--end::Page Snippets -->
|
||||||
|
|
||||||
<!--begin::Extra Scripts -->
|
<!--begin::Extra Scripts -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>
|
||||||
|
<script src="/assets/js/moment.min.js" type="text/javascript"></script>
|
||||||
|
<script src="/assets/js/notification.js" type="text/javascript"></script>
|
||||||
|
<script>
|
||||||
|
// notifications
|
||||||
|
var notif = new NotificationHandler({
|
||||||
|
'notif_ajax_url': '{{ url('notification_ajax_list') }}',
|
||||||
|
'icons': {
|
||||||
|
'jo_new': 'flaticon-placeholder-3 kt-font-brand',
|
||||||
|
'jo_cancel': 'fa fa-times-circle kt-font-danger',
|
||||||
|
'rider_accept': 'fa fa-motorcycle kt-font-success',
|
||||||
|
'rider_reject': 'fa fa-exclamation-triangle kt-font-danger'
|
||||||
|
},
|
||||||
|
'default_icon': 'fa fa-asterisk kt-font-brand',
|
||||||
|
});
|
||||||
|
notif.clearAll();
|
||||||
|
notif.loadAll();
|
||||||
|
notif.listen('{{ app.user.id }}', '{{ mqtt_host }}', {{ mqtt_port }}, {{ ssl_enable }});
|
||||||
|
</script>
|
||||||
{% block scripts %}{% endblock %}
|
{% block scripts %}{% endblock %}
|
||||||
<!--end::Extra Scripts -->
|
<!--end::Extra Scripts -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue