hfkfhkfhgjkuhgfkjfghkj
This commit is contained in:
85
app/plugins/notifications/controllers/admin/notifications.php
Executable file
85
app/plugins/notifications/controllers/admin/notifications.php
Executable file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/notifications/controllers/admin/notifications.php
|
||||
*
|
||||
* This is the notifications admin controller.
|
||||
*
|
||||
* @package TP Notifications
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers\Admin;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Classes\AdminController;
|
||||
use TheTempusProject\Models\Notification as NotificationsModel;
|
||||
use TheTempusProject\Models\Group;
|
||||
use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Houdini\Classes\Forms;
|
||||
use TheTempusProject\Classes\Forms as FormChecker;
|
||||
|
||||
class Notifications extends AdminController {
|
||||
protected static $notifications;
|
||||
public static $user;
|
||||
public static $group;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$title = 'Admin - Notifications';
|
||||
self::$notifications = new NotificationsModel;
|
||||
self::$user = new User;
|
||||
self::$group = new Group;
|
||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/Notifications' );
|
||||
Components::set( 'ADMINNAV', $view );
|
||||
}
|
||||
|
||||
public function index( $data = null ) {
|
||||
// this is just a simple form to allow admins to send notifications
|
||||
return $this->create();
|
||||
}
|
||||
|
||||
public function create() {
|
||||
$select = Forms::getSelectHtml(
|
||||
'groupSelect',
|
||||
self::$group->listGroupsSimple( true )
|
||||
);
|
||||
Components::set( 'groupSelect', $select );
|
||||
if ( ! Input::exists( 'submit' ) ) {
|
||||
return Views::view( 'notifications.admin.send' );
|
||||
}
|
||||
if ( ! FormChecker::check( 'createNotification' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
|
||||
return Views::view( 'notifications.admin.send' );
|
||||
}
|
||||
if ( Input::exists( 'expires' ) ) {
|
||||
$expiresAt = time() + intval( Input::post( 'expires' ) );
|
||||
} else {
|
||||
$expiresAt = 0;
|
||||
}
|
||||
|
||||
if ( Input::exists( 'groupSelect' ) && Input::post( 'groupSelect' ) != 0 && Input::post( 'groupSelect' ) != 'all' ) {
|
||||
$list = self::$group->listMembers( Input::post( 'groupSelect' ) );
|
||||
} else {
|
||||
$list = self::$user->userList();
|
||||
}
|
||||
|
||||
$results = [];
|
||||
foreach ( $list as $recipient ) {
|
||||
$results[] = self::$notifications->create( Input::post( 'notification' ), 'Admin Issued', $recipient->ID, $expiresAt );
|
||||
}
|
||||
|
||||
// $result = self::$notifications->create( Input::post( 'notification' ), 'Admin Issued', XXXXXXX_user_idsXXXXXX, $expiresAt );
|
||||
if ( ! empty( $results ) ) {
|
||||
Issues::add( 'success', 'Your notification has been sent.' );
|
||||
} else {
|
||||
Issues::add( 'error', [ 'There was an unknown error submitting your data.' => Check::userErrors() ] );
|
||||
}
|
||||
Views::view( 'notifications.admin.send' );
|
||||
}
|
||||
}
|
79
app/plugins/notifications/controllers/notifications.php
Executable file
79
app/plugins/notifications/controllers/notifications.php
Executable file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/notifications/controllers/notifications.php
|
||||
*
|
||||
* This is the home controller for the notifications plugin.
|
||||
*
|
||||
* @package TP Notifications
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Models\Notification as NotificationsModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
|
||||
class Notifications extends Controller {
|
||||
protected static $notifications;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$notifications = new NotificationsModel;
|
||||
self::$title = 'Notifications - {SITENAME}';
|
||||
self::$pageDescription = 'Your recent notifications';
|
||||
if ( ! App::$isLoggedIn ) {
|
||||
Session::flash( 'error', 'You do not have permission to access this page.' );
|
||||
return Redirect::home();
|
||||
}
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$notifications = self::$notifications->getByUser( 10 );
|
||||
Views::view( 'notifications.list', $notifications );
|
||||
}
|
||||
|
||||
public function markRead( $id = null ) {
|
||||
$notification = self::$notifications->findById( $id );
|
||||
if ( $notification == false ) {
|
||||
Issues::add( 'error', 'Notification not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $notification->userID != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this notification.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$notifications->markSeen( $id );
|
||||
if ( $result == true ) {
|
||||
Issues::add( 'success', 'Notification marked as read.' );
|
||||
} else {
|
||||
Issues::add( 'notice', 'There was an problem updating your notification.' );
|
||||
}
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
public function delete( $id = null ) {
|
||||
$notification = self::$notifications->findById( $id );
|
||||
if ( $notification == false ) {
|
||||
Issues::add( 'error', 'Notification not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $notification->userID != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this notification.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$notifications->delete( $id );
|
||||
if ( $result == true ) {
|
||||
Issues::add( 'success', 'Notification deleted.' );
|
||||
} else {
|
||||
Issues::add( 'notice', 'There was an problem deleting your notification.' );
|
||||
}
|
||||
return $this->index();
|
||||
}
|
||||
}
|
41
app/plugins/notifications/forms.php
Executable file
41
app/plugins/notifications/forms.php
Executable file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/notifications/forms.php
|
||||
*
|
||||
* This houses all of the form checking functions for this plugin.
|
||||
*
|
||||
* @package TP Notifications
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins\Notifications;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
|
||||
class NotificationForms extends Forms {
|
||||
/**
|
||||
* Adds these functions to the form list.
|
||||
*/
|
||||
public function __construct() {
|
||||
self::addHandler( 'createNotification', __CLASS__, 'createNotification' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the createNotification form.
|
||||
*
|
||||
* @return {bool}
|
||||
*/
|
||||
public static function createNotification() {
|
||||
if ( ! Input::exists( 'notification' ) ) {
|
||||
Check::addUserError( 'You must provide a notification.' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
new NotificationForms;
|
146
app/plugins/notifications/models/notification.php
Executable file
146
app/plugins/notifications/models/notification.php
Executable file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/notifications/models/notification.php
|
||||
*
|
||||
* This class is used for the manipulation of the notifications database table.
|
||||
*
|
||||
* @package TP Notifications
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Canary\Classes\CustomException;
|
||||
|
||||
class Notification extends DatabaseModel {
|
||||
public $tableName = 'notifications';
|
||||
public $databaseMatrix = [
|
||||
[ 'notification', 'text', '' ],
|
||||
[ 'origin', 'varchar', '128' ],
|
||||
[ 'userID', 'int', '11' ],
|
||||
[ 'createdAt', 'int', '11' ],
|
||||
[ 'expiresAt', 'int', '11' ],
|
||||
[ 'deletedAt', 'int', '11' ],
|
||||
[ 'seenAt', 'int', '11' ],
|
||||
];
|
||||
|
||||
public function getUnreadCount( $userID ) {
|
||||
$result = self::$db->get(
|
||||
$this->tableName,
|
||||
[
|
||||
'userID', '=', $userID,
|
||||
'AND',
|
||||
'deletedAt', '=', '0',
|
||||
'AND',
|
||||
'seenAt', '=', '0',
|
||||
'AND',
|
||||
'expiresAt', '<', time(),
|
||||
]
|
||||
);
|
||||
return $result->count();
|
||||
}
|
||||
|
||||
public function create( $notification, $origin, $userID, $expiresAt = '0', $deletedAt = '0', $seenAt = '0' ) {
|
||||
$fields = [
|
||||
'notification' => $notification,
|
||||
'origin' => $origin,
|
||||
'userID' => $userID,
|
||||
'createdAt' => time(),
|
||||
'expiresAt' => $expiresAt,
|
||||
'deletedAt' => $deletedAt,
|
||||
'seenAt' => $seenAt,
|
||||
];
|
||||
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
||||
Debug::info( 'Events::create - failed to insert to db' );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function getByUser( $limit = 0 ) {
|
||||
$whereClause = [
|
||||
'userID', '=', App::$activeUser->ID,
|
||||
'AND',
|
||||
'deletedAt', '=', '0',
|
||||
'AND',
|
||||
'expiresAt', '<', time(),
|
||||
];
|
||||
if ( empty( $limit ) ) {
|
||||
$notifications = self::$db->get( $this->tableName, $whereClause );
|
||||
} else {
|
||||
$notifications = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$notifications->count() ) {
|
||||
Debug::info( 'Notification:getByUser No Notifications found' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $notifications->results() );
|
||||
}
|
||||
|
||||
public function markSeen( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Notifications: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'seenAt' => time(),
|
||||
];
|
||||
$notification = self::findById( $id );
|
||||
if ( ! $notification ) {
|
||||
Debug::error( "Notifications: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'notificationUpdate' );
|
||||
Debug::error( "Notifications: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete( $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( 'Notifications: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'deletedAt' => time(),
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||
new CustomException( 'notificationDelete' );
|
||||
Debug::error( "Notifications: $id not updated" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function filter( $messageArray, $filters = [] ) {
|
||||
$out = [];
|
||||
foreach ( $messageArray as $message ) {
|
||||
if ( !is_object( $message ) ) {
|
||||
$message = $messageArray;
|
||||
$end = true;
|
||||
}
|
||||
if ( $message->seenAt == 0 ) {
|
||||
$message->unseenBadge = Views::simpleView( 'notifications.unseenBadge' );
|
||||
$message->markReadLink = '<a href="{ROOT_URL}notifications/markRead/'.$message->ID.'" class="btn btn-sm btn-primary"><i class="fa-solid fa-fw fa-envelope-open"></i></a>';
|
||||
} else {
|
||||
$message->unseenBadge = '';
|
||||
$message->markReadLink = '';
|
||||
}
|
||||
$out[] = (object) $message;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
64
app/plugins/notifications/plugin.php
Executable file
64
app/plugins/notifications/plugin.php
Executable file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/notifications/plugin.php
|
||||
*
|
||||
* This houses all of the main plugin info and functionality.
|
||||
*
|
||||
* @package TP Notifications
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins;
|
||||
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Classes\Plugin;
|
||||
use TheTempusProject\Models\Notification;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
|
||||
class Notifications extends Plugin {
|
||||
public $pluginName = 'TP Notifications';
|
||||
public $pluginAuthor = 'JoeyK';
|
||||
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||
public $modelVersion = '1.0';
|
||||
public $pluginVersion = '3.0';
|
||||
public $pluginDescription = 'A simple plugin which adds a site wide notification system.';
|
||||
public $permissionMatrix = [
|
||||
'sendNotifications' => [
|
||||
'pretty' => 'Can send notifications',
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
public $admin_links = [
|
||||
[
|
||||
'text' => '<i class="fa fa-fw fa-bell"></i> Notify',
|
||||
'url' => '{ROOT_URL}admin/notifications',
|
||||
],
|
||||
];
|
||||
private static $loaded = false;
|
||||
public function __construct( $load = false ) {
|
||||
parent::__construct( $load );
|
||||
if ( $this->checkEnabled() && App::$isLoggedIn ) {
|
||||
$notifications = new Notification;
|
||||
Components::set( 'notificationCount', $notifications->getUnreadCount( App::$activeUser->ID ) );
|
||||
if ( $notifications->getUnreadCount( App::$activeUser->ID ) > 0 ) {
|
||||
$messageBadge = Views::simpleView( 'notifications.badge' );
|
||||
} else {
|
||||
$messageBadge = '';
|
||||
}
|
||||
Components::set( 'NBADGE', $messageBadge );
|
||||
if ( ! self::$loaded ) {
|
||||
if ( App::$isLoggedIn ) {
|
||||
Components::set( 'recentNotifications', Views::simpleView( 'notifications.nav.recentNotificationsDropdown', $notifications->getByUser( 10 ) ) );
|
||||
} else {
|
||||
Components::set( 'recentNotifications', '' );
|
||||
}
|
||||
App::$topNavRight .= '{recentNotifications}';
|
||||
App::$topNavRightDropdown .= '<li><a href="{ROOT_URL}notifications" class="dropdown-item"><i class="fa fa-fw fa-bell"></i> Notifications {NBADGE}</a></li>';
|
||||
self::$loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
61
app/plugins/notifications/views/admin/send.html
Executable file
61
app/plugins/notifications/views/admin/send.html
Executable file
@ -0,0 +1,61 @@
|
||||
<div class="context-main-bg context-main p-3">
|
||||
<legend class="text-center">Send Notification</legend>
|
||||
<hr>
|
||||
{ADMIN_BREADCRUMBS}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<fieldset>
|
||||
<!-- Group -->
|
||||
<div class="mb-3 row">
|
||||
<label for="groupSelect" class="col-lg-3 col-form-label text-end">Group:</label>
|
||||
<div class="col-lg-6">
|
||||
{groupSelect}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recipients -->
|
||||
<div class="mb-3 row">
|
||||
<label for="expiration" class="col-lg-3 col-form-label text-end">Expiration:</label>
|
||||
<div class="col-lg-6">
|
||||
<select class="form-control" name="expiration" id="expiration">
|
||||
<option value="0">forever</option>
|
||||
<option value="1800">30 Minutes</option>
|
||||
<option value="3600">60 Minutes</option>
|
||||
<option value="14400">4 hours</option>
|
||||
<option value="28800">8 hours</option>
|
||||
<option value="43200">12 hours</option>
|
||||
<option value="86400">24 hours</option>
|
||||
<option value="172800">2 days</option>
|
||||
<option value="259200">3 days</option>
|
||||
<option value="432000">5 days</option>
|
||||
<option value="604800">7 days</option>
|
||||
<option value="1209600">2 weeks</option>
|
||||
<option value="1814400">3 weeks</option>
|
||||
<option value="2419200">4 weeks</option>
|
||||
<option value="2592000">1 month</option>
|
||||
<option value="5184000">2 months</option>
|
||||
<option value="7776000">3 months</option>
|
||||
<option value="15552000">6 months</option>
|
||||
<option value="31536000">12 months</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notification -->
|
||||
<div class="mb-3 row">
|
||||
<label for="notification" class="col-lg-3 col-form-label text-end">Notification:</label>
|
||||
<div class="col-lg-6">
|
||||
<textarea class="form-control" name="notification" id="notification" rows="6" maxlength="2000" required></textarea>
|
||||
<small class="form-text text-muted">Max: 2000 characters</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden Token -->
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
</fieldset>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="text-center">
|
||||
<button type="submit" name="submit" value="submit" class="btn btn-primary btn-lg center-block">Send</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
1
app/plugins/notifications/views/badge.html
Executable file
1
app/plugins/notifications/views/badge.html
Executable file
@ -0,0 +1 @@
|
||||
<span class="badge bg-danger rounded-pill">{notificationCount}</span>
|
41
app/plugins/notifications/views/list.html
Executable file
41
app/plugins/notifications/views/list.html
Executable file
@ -0,0 +1,41 @@
|
||||
|
||||
<div class="m-2 m-lg-4">
|
||||
<div class="col-12 mx-5 col-sm-10 col-lg-8 mx-auto p-4 rounded shadow-sm context-main-bg">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<legend class="text-center">Notifications</legend>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 90%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr {unseenBadge}>
|
||||
<td class=" context-main">{notification}</td>
|
||||
<td>
|
||||
{markReadLink}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{ROOT_URL}notifications/delete/{ID}" class="btn btn-sm btn-danger">
|
||||
<i class="fa fa-fw fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="3" class="text-center context-main">
|
||||
No Notifications
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
41
app/plugins/notifications/views/nav/recentNotificationsDropdown.html
Executable file
41
app/plugins/notifications/views/nav/recentNotificationsDropdown.html
Executable file
@ -0,0 +1,41 @@
|
||||
<!-- Notifications Dropdown -->
|
||||
<div class="dropdown nav-item mx-2 my-2 my-lg-0">
|
||||
<a
|
||||
href="#"
|
||||
class="d-flex align-items-center text-white text-decoration-none dropdown-toggle"
|
||||
id="notificationsDropdown"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false">
|
||||
<i class="fa fa-fw fa-bell"></i><span class="">{NBADGE}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-dark dropdown-menu-end text-small shadow" aria-labelledby="notificationsDropdown">
|
||||
{LOOP}
|
||||
<!-- Notification Item -->
|
||||
<li>
|
||||
<a href="{ROOT_URL}notifications" class="dropdown-item">
|
||||
<div class="media">
|
||||
<div class="media-body">
|
||||
<p class="small text-muted mb-1"><i class="fa fa-clock-o me-1"></i> {DTC}{createdAt}{/DTC}</p>
|
||||
<span>{notification}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li class="px-3 text-center">
|
||||
<strong>No Notifications</strong>
|
||||
</li>
|
||||
{/ALT}
|
||||
<!-- Footer -->
|
||||
<li>
|
||||
<hr class="dropdown-divider">
|
||||
</li>
|
||||
<li>
|
||||
<a href="/notifications" class="dropdown-item text-center">
|
||||
See All Notifications
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
1
app/plugins/notifications/views/unseenBadge.html
Executable file
1
app/plugins/notifications/views/unseenBadge.html
Executable file
@ -0,0 +1 @@
|
||||
class="bg-info"
|
Reference in New Issue
Block a user