Merge branch 'update-notification' into 'dev'

update notification

See merge request TheGamecraft/c-cms!104
This commit is contained in:
Mathieu Lagace
2020-07-27 20:45:58 +00:00
28 changed files with 1167 additions and 47 deletions

View File

@@ -3,7 +3,7 @@
/**
* A helper file for Laravel, to provide autocomplete information to your IDE
* Generated for Laravel 7.16.1 on 2020-06-17 17:36:56.
* Generated for Laravel 7.16.1 on 2020-07-01 15:16:34.
*
* This file should not be included in your code, only analyzed by your IDE!
*
@@ -15959,6 +15959,209 @@ namespace Nexmo\Laravel\Facade {
}
namespace PragmaRX\Version\Package {
/**
*
*
*/
class Facade {
/**
* Get a version.
*
* @param $type
* @return string
* @static
*/
public static function getGit()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->getGit();
}
/**
* Get the current version.
*
* @return string
* @static
*/
public static function current()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->current();
}
/**
* Get the current object instance.
*
* @return \PragmaRX\Version\Package\Version
* @static
*/
public static function instance()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->instance();
}
/**
* Get a properly formatted version.
*
* @param $type
* @return mixed|null
* @static
*/
public static function format($type = null)
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->format($type);
}
/**
* Is it in absorb mode?
*
* @param $type
* @return bool
* @static
*/
public static function isInAbsorbMode()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->isInAbsorbMode();
}
/**
* Is version in absorb mode?
*
* @param $type
* @return bool
* @static
*/
public static function isVersionInAbsorbMode()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->isVersionInAbsorbMode();
}
/**
* Is build in absorb mode?
*
* @param $type
* @return bool
* @static
*/
public static function isBuildInAbsorbMode()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->isBuildInAbsorbMode();
}
/**
* Is timestamp in absorb mode?
*
* @param $type
* @return bool
* @static
*/
public static function isTimestampInAbsorbMode()
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->isTimestampInAbsorbMode();
}
/**
* Set the config file stub.
*
* @param string $configFileStub
* @static
*/
public static function setConfigFileStub($configFileStub)
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->setConfigFileStub($configFileStub);
}
/**
* Load package YAML configuration.
*
* @param $path
* @return \Illuminate\Support\Collection
* @static
*/
public static function loadConfig($path = null)
{
/** @var \PragmaRX\Version\Package\Version $instance */
return $instance->loadConfig($path);
}
}
}
namespace PragmaRX\Yaml\Package {
/**
*
*
*/
class Facade {
/**
* Load yaml files from directory and add to Laravel config.
*
* @param string $path
* @param string $configKey
* @return \PragmaRX\Yaml\Package\Collection
* @static
*/
public static function loadToConfig($path, $configKey)
{
/** @var \PragmaRX\Yaml\Package\Yaml $instance */
return $instance->loadToConfig($path, $configKey);
}
/**
* Load all yaml files from a directory.
*
* @param $path
* @return \Illuminate\Support\Collection
* @static
*/
public static function loadFromDirectory($path)
{
/** @var \PragmaRX\Yaml\Package\Yaml $instance */
return $instance->loadFromDirectory($path);
}
/**
* Load yaml file.
*
* @param $file
* @return mixed|string
* @static
*/
public static function loadFile($file)
{
/** @var \PragmaRX\Yaml\Package\Yaml $instance */
return $instance->loadFile($file);
}
/**
* Get this object instance.
*
* @return \PragmaRX\Yaml\Package\Yaml
* @static
*/
public static function instance()
{
/** @var \PragmaRX\Yaml\Package\Yaml $instance */
return $instance->instance();
}
}
}
namespace {
@@ -18909,6 +19112,10 @@ namespace {
class Flare extends \Facade\Ignition\Facades\Flare {}
class Nexmo extends \Nexmo\Laravel\Facade\Nexmo {}
class Version extends \PragmaRX\Version\Package\Facade {}
class Yaml extends \PragmaRX\Yaml\Package\Facade {}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Notifications\DatabaseNotification;
class NotificationController extends Controller
{
public function markAsRead($id)
{
$n = DatabaseNotification::find($id);
$n->read_at = date('Y-m-d h:i:s');
$n->save();
}
public function markAllAsRead()
{
$notifications = \Auth::user()->unreadNotifications;
foreach ($notifications as $n)
{
$n->read_at = date('Y-m-d h:i:s');
$n->save();
}
return $notifications;
}
}

View File

@@ -272,4 +272,9 @@ class UserController extends Controller
{
return view('admin.user.course',['courses' => User::find($id)->courses]);
}
public function userNotification()
{
return view('admin.user.profil.notifications',['notifications' => \Auth::user()->notifications]);
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
@@ -13,6 +14,7 @@ class Alert extends Notification
protected $fromUser;
protected $myNotification;
private $myUrl;
/**
* Create a new notification instance.
@@ -34,7 +36,7 @@ class Alert extends Notification
*/
public function via($notifiable)
{
return ['database'];
return ['database','broadcast'];
}
/**
@@ -51,4 +53,18 @@ class Alert extends Notification
'url' => $this->myUrl,
];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'from' => $this->fromUser,
'msg' => $this->myNotification,
'url' => $this->myUrl,
]);
}
public function broadcastType()
{
return 'notification.alert';
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class ScheduleNotification extends Notification
{
use Queueable;
protected String $name;
protected String $msg;
protected String $url;
protected String $icon;
/**
* Create a new notification instance.
*
* @param String $name
* @param String $msg
* @param String $url
*/
public function __construct(String $name,String $msg,String $url)
{
$this->name = $name;
$this->msg = $msg;
$this->url = $url;
$this->icon = '<i class="far fa-calendar"></i>';
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['database','broadcast'];
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'name' => $this->name,
'msg' => $this->msg,
'url' => $this->url,
'icon' => $this->icon
];
}
public function broadcastType()
{
return 'notification.schedule';
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class SystemNotification extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@@ -2,8 +2,10 @@
namespace App;
use Carbon\Carbon;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use phpDocumentor\Reflection\Types\Collection;
/**
* App\User
@@ -371,4 +373,18 @@ class User extends Authenticatable
{
return $this->permission($perm);
}
public function getNotificationByDay()
{
return \Auth::user()->notifications->groupBy(function ($val) {
return Carbon::parse($val->created_at)->format('Y-m-d');
});
}
public function getNotificationForUI(int $number = 8)
{
return \Auth::user()->notifications->take($number)->groupBy(function ($val) {
return Carbon::parse($val->created_at)->format('Y-m-d');
});
}
}

View File

@@ -5,7 +5,7 @@
"license": "MIT",
"type": "project",
"require": {
"php": "^7.2",
"php": "^7.4",
"barryvdh/laravel-dompdf": "^0.8.4",
"barryvdh/laravel-ide-helper": "2.7.0",
"davejamesmiller/laravel-breadcrumbs": "5.3.2",
@@ -19,7 +19,8 @@
"laravel/ui": "^2.0",
"nao-pon/flysystem-google-drive": "^1.1",
"nexmo/client": "^2.0",
"pragmarx/version": "^1.2"
"pragmarx/version": "^1.2",
"pusher/pusher-php-server": "~4.0"
},
"require-dev": {
"filp/whoops": "^2.0",

183
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7c071faf4bcbceff2849f97052c64f69",
"content-hash": "e2dc7086eb67a56fb816e262934a3a2a",
"packages": [
{
"name": "barryvdh/laravel-dompdf",
@@ -3344,6 +3344,133 @@
],
"time": "2020-06-17T14:59:55+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v9.99.99",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
"shasum": ""
},
"require": {
"php": "^7"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*",
"vimeo/psalm": "^1"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"polyfill",
"pseudorandom",
"random"
],
"time": "2018-07-02T15:55:56+00:00"
},
{
"name": "paragonie/sodium_compat",
"version": "v1.13.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/sodium_compat.git",
"reference": "bbade402cbe84c69b718120911506a3aa2bae653"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/bbade402cbe84c69b718120911506a3aa2bae653",
"reference": "bbade402cbe84c69b718120911506a3aa2bae653",
"shasum": ""
},
"require": {
"paragonie/random_compat": ">=1",
"php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8"
},
"require-dev": {
"phpunit/phpunit": "^3|^4|^5|^6|^7"
},
"suggest": {
"ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.",
"ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security."
},
"type": "library",
"autoload": {
"files": [
"autoload.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com"
},
{
"name": "Frank Denis",
"email": "jedisct1@pureftpd.org"
}
],
"description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists",
"keywords": [
"Authentication",
"BLAKE2b",
"ChaCha20",
"ChaCha20-Poly1305",
"Chapoly",
"Curve25519",
"Ed25519",
"EdDSA",
"Edwards-curve Digital Signature Algorithm",
"Elliptic Curve Diffie-Hellman",
"Poly1305",
"Pure-PHP cryptography",
"RFC 7748",
"RFC 8032",
"Salpoly",
"Salsa20",
"X25519",
"XChaCha20-Poly1305",
"XSalsa20-Poly1305",
"Xchacha20",
"Xsalsa20",
"aead",
"cryptography",
"ecdh",
"elliptic curve",
"elliptic curve cryptography",
"encryption",
"libsodium",
"php",
"public-key cryptography",
"secret-key cryptography",
"side-channel resistant"
],
"time": "2020-03-20T21:48:09+00:00"
},
{
"name": "phenx/php-font-lib",
"version": "0.5.2",
@@ -4345,6 +4472,60 @@
],
"time": "2020-05-03T19:32:03+00:00"
},
{
"name": "pusher/pusher-php-server",
"version": "v4.1.4",
"source": {
"type": "git",
"url": "https://github.com/pusher/pusher-http-php.git",
"reference": "e75e5715e3b651ec20dee5844095aadefab81acb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pusher/pusher-http-php/zipball/e75e5715e3b651ec20dee5844095aadefab81acb",
"reference": "e75e5715e3b651ec20dee5844095aadefab81acb",
"shasum": ""
},
"require": {
"ext-curl": "*",
"paragonie/sodium_compat": "^1.6",
"php": "^7.1",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^7.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.4-dev"
}
},
"autoload": {
"psr-4": {
"Pusher\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Library for interacting with the Pusher REST API",
"keywords": [
"events",
"messaging",
"php-pusher-server",
"publish",
"push",
"pusher",
"real time",
"real-time",
"realtime",
"rest",
"trigger"
],
"time": "2020-04-14T15:20:04+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",

View File

@@ -170,7 +170,7 @@ return [
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\GoogleDriveServiceProvider::class,

View File

@@ -5,7 +5,7 @@ current:
major: 3
minor: 2
patch: 5
prerelease: 1-gb79c54fd
prerelease: 8-gc16d1e7e
buildmetadata: ''
commit: 41845
timestamp:

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateWebSocketsStatisticsEntriesTable extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::create('websockets_statistics_entries', function (Blueprint $table) {
$table->increments('id');
$table->string('app_id');
$table->integer('peak_connection_count');
$table->integer('websocket_message_count');
$table->integer('api_message_count');
$table->nullableTimestamps();
});
}
/**
* Reverse the migrations.
*/
public function down()
{
Schema::dropIfExists('websockets_statistics_entries');
}
}

23
package-lock.json generated
View File

@@ -5122,7 +5122,8 @@
},
"js-yaml": {
"version": "3.7.0",
"resolved": "",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
"integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
"dev": true,
"requires": {
"argparse": "^1.0.7",
@@ -5215,6 +5216,11 @@
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
"laravel-echo": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.8.0.tgz",
"integrity": "sha512-hEHmNKUgV3fR2Do/2PKxfO3OiLmbjX89tahGEi4urS8JEuy/yoRtFToOJXV9ChtOpRqxo7trrygPOvXLwvc/6A=="
},
"laravel-mix": {
"version": "2.1.14",
"resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-2.1.14.tgz",
@@ -8648,6 +8654,21 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"pusher-js": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-6.0.3.tgz",
"integrity": "sha512-l0MHlrpG+D4R6jj+vjqnJNjawBqKCjQ4Y/YARNsWFbXGKNl77xX8pUpbv55Al+dFHGkc7wI2fDXw/BDLleF9Lg==",
"requires": {
"tweetnacl": "^1.0.3"
},
"dependencies": {
"tweetnacl": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
}
}
},
"q": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",

View File

@@ -21,6 +21,8 @@
},
"dependencies": {
"ajv": "^6.12.2",
"laravel-echo": "^1.8.0",
"pusher-js": "^6.0.3",
"sweetalert2": "^7.33.1"
}
}

20
public/css/custom.css vendored
View File

@@ -53,6 +53,26 @@
}
}
.dropdown-notification {
min-width: 300px !important;
}
.dropdown-notification .card-header {
padding: 0.4rem !important;
}
.notification-success {
border-left: solid #4caf50 3px !important;
}
.notification-success svg {
color: #4caf50;
}
.notification-table td {
padding: 10px !important;
margin: 5px !important;
}
.cursor {
cursor: pointer;
}

63
public/js/app.js vendored
View File

@@ -13,4 +13,67 @@ function extendSidebar()
$('#'+foo.attr('parent')).collapse('show');
$('#link-'+foo.attr('parent')).addClass('active');
}
}
function markNotificationAsRead(id)
{
$.post('/api/notification/'+id+'/read?api_token='+api_token, function () {
$('#'+id).removeClass('notification-success');
$('#'+id).removeClass('cursor');
$('#'+id).removeAttr('onclick');
$('#notification-'+id).removeClass('notification-success');
$('#notification-'+id).removeClass('cursor');
$('#notification-'+id).removeAttr('onclick');
updateNotificationNumber(-1);
});
}
function markAllNotificationAsRead()
{
$.get('/api/notification/allRead',{"api_token": api_token}, function (data) {
$.each(data,function (key,value) {
$('#'+value.id).removeClass('notification-success');
$('#'+value.id).removeClass('cursor');
$('#'+value.id).removeAttr('onclick');
$('#notification-'+value.id).removeClass('notification-success');
$('#notification-'+value.id).removeClass('cursor');
$('#notification-'+value.id).removeAttr('onclick');
updateNotificationNumber(-1);
})
});
}
function updateNotificationNumber(foo)
{
span = $('#notification-number');
if (parseInt(span.html())+parseInt(foo) == 0)
{
span.addClass('d-none');
}
else
{
span.removeClass('d-none');
}
span.html(parseInt(span.html())+parseInt(foo));
}
function addNotification(notification)
{
let notificationcontainer = $("#notification-container");
notificationcontainer.prepend(
'<li id="'+notification.id+'" class="list-group-item cursor notification-success" style="border-bottom: solid 1px lightgrey" onclick="markNotificationAsRead(\''+notification.id+'\')" >\n' +
'<div class="d-flex">' +
'<div style="min-width: 2rem">\n' +
notification.icon +
'</div>\n' +
'<div>\n' +
'<b class="mb-1">'+notification.name+'</b>\n' +
'<p class="text-muted m-0">'+notification.msg+'</p>\n' +
'</div>\n' +
'</div>\n' +
'</li>'
);
updateNotificationNumber(+1);
}

312
public/js/bootstrap.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
{
"/js/bootstrap.js": "/js/bootstrap.js",
"/css/app.css": "/css/app.css",
"/css/material-dashboard.css": "/css/material-dashboard.css",
"/css/custom.css": "/css/custom.css"

View File

@@ -2,18 +2,6 @@
window._ = require('lodash');
window.Popper = require('popper.js').default;
/**
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
* for JavaScript based Bootstrap features such as modals and tabs. This
* code may be modified to fit the specific needs of your application.
*/
try {
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
@@ -44,13 +32,17 @@ if (token) {
* allows your team to easily build robust real-time web applications.
*/
// import Echo from 'laravel-echo'
import Echo from 'laravel-echo'
// window.Pusher = require('pusher-js');
window.Pusher = require('pusher-js');
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: process.env.MIX_PUSHER_APP_KEY,
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
// encrypted: true
// });
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true
});
window.Echo.private('App.User.2').notification((notification) => {
addNotification(notification);
});

20
resources/custom.css vendored
View File

@@ -53,6 +53,26 @@
}
}
.dropdown-notification {
min-width: 300px !important;
}
.dropdown-notification .card-header {
padding: 0.4rem !important;
}
.notification-success {
border-left: solid #4caf50 3px !important;
}
.notification-success svg {
color: #4caf50;
}
.notification-table td {
padding: 10px !important;
margin: 5px !important;
}
.cursor {
cursor: pointer;
}

View File

@@ -0,0 +1,43 @@
@extends('layouts.admin.main')
@section('content')
<div class="row">
<div class="card">
<div class="card-header card-header-primary">
<h4 class="card-title">Mes notifications</h4>
</div>
<div class="card-body">
<div class="material-datatables">
<table id="notification-table" class="table table-striped w-100 notification-table">
<thead>
<td>Notifications</td>
</thead>
<tbody>
@foreach($notifications as $n)
<tr>
<td id="notification-{{$n->id}}" @if($n->read_at == null) class="notification-success cursor" onclick="markNotificationAsRead('{{$n->id}}')" @endif>
@if(isset($n->data['title']))
{{$n->data['title']}}
@else
<b>{{$n->data['name']}}</b><br>
{{$n->data['msg']}}
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('custom_scripts')
<script>
$(document).ready(function() {
$('#notification-table').DataTable();
} );
</script>
@endsection

View File

@@ -11,6 +11,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="user-id" content="{{ Auth::user()->id }}">
<!-- Favicon, Icon and Font -->
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons" />

View File

@@ -1,9 +1,3 @@
<?php
$nbOfNotification = 0;
foreach (Auth::user()->unreadNotifications as $notification) {
$nbOfNotification = $nbOfNotification + 1;
}
?>
<nav class="navbar navbar-expand-lg navbar-transparent navbar-absolute fixed-top ">
<div class="container-fluid">
<div class="navbar-wrapper">
@@ -43,20 +37,50 @@ foreach (Auth::user()->unreadNotifications as $notification) {
<li class="nav-item dropdown">
<a class="nav-link" href="http://example.com" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="material-icons">notifications</i>
@if ($nbOfNotification != 0)
<span class="notification">{{ $nbOfNotification }}</span>
@endif
<span id="notification-number" number="{{count(Auth::user()->unreadNotifications)}}" class="notification @if (count(Auth::user()->unreadNotifications) == 0) d-none @endif">{{ count(Auth::user()->unreadNotifications) }}</span>
<p class="d-lg-none d-md-block">
Notifications
</p>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdownMenuLink">
@foreach (Auth::user()->unreadNotifications as $notification)
<a class="dropdown-item" href="#">{{$notification->data['msg']}}</a>
<div class="dropdown-menu dropdown-menu-right dropdown-notification" aria-labelledby="navbarDropdownMenuLink">
<div class="card-header">
<h6 class="text-center m-0">Notification</h6>
</div>
<div class="card-body pt-2" style="max-height: 450px;overflow: auto">
<div class="row">
<div class="col-6">
</div>
<div class="col-6 text-right">
<a class="btn btn-sm btn-outline-info text-info" onclick="markAllNotificationAsRead()">Tous lu</a>
</div>
</div>
@foreach(Auth::user()->getNotificationForUI() as $key => $notificationGroup)
<small class="text">{{$key}}</small>
<div class="card mb-3 mt-1" style="width: 18rem;">
<ul id="notification-container" class="list-group list-group-flush">
@foreach($notificationGroup as $notification)
<li id="{{$notification->id}}" class="list-group-item @if($notification->read_at == null)cursor notification-success @endif" style="border-bottom: solid 1px lightgrey" @if($notification->read_at == null) onclick="markNotificationAsRead('{{$notification->id}}')" @endif>
<div class="d-flex">
<div style="min-width: 2rem">
@if(isset($notification->data['icon']))
{!! $notification->data['icon'] !!}
@endif
</div>
<div>
<b class="mb-1">{{$notification->data['name']}}</b>
<p class="text-muted m-0">{{$notification->data['msg']}}</p>
</div>
</div>
</li>
@endforeach
</ul>
</div>
@endforeach
@if ($nbOfNotification == 0)
<a class="dropdown-item">Aucune notification</a>
@endif
</div>
<div class="card-footer">
<a href="/admin/profil/notifications" class="btn btn-outline-info text-info">Afficher toutes mes notifications</a>
</div>
</div>
</li>
<li class="nav-item dropdown">

View File

@@ -6,7 +6,9 @@
<script src="/js/core/bootstrap-material-design.min.js"></script>
<script src="/js/material-dashboard.js"></script>
<script type="module" src="/js/bootstrap.js"></script>
<script src="/js/app.js"></script>
<!-- Plugin for the momentJs -->
<script src="/js/plugins/moment.min.js"></script>
<!-- Plugin for Sweet Alert -->

View File

@@ -87,6 +87,9 @@ Route::middleware('auth:api')->group(function () {
Route::delete('/ocom/{id}','OCOMController@destroy');
Route::post('/notification/{id}/read','NotificationController@markAsRead');
Route::get('/notification/allRead','NotificationController@markAllAsRead');
});
Route::get('/admin/ping', function(){
$users = \App\User::all();

View File

@@ -275,6 +275,12 @@ Breadcrumbs::for('admin.profil.courses', function ($trail) {
$trail->push('Mes cours', route('admin.profil.courses'));
});
// Admin > Profil > Adress
Breadcrumbs::for('admin.profil.notifications', function ($trail) {
$trail->parent('admin.profil');
$trail->push('Mes notifications', route('admin.profil.notifications'));
});
// Admin > Drive
Breadcrumbs::for('admin.drive', function ($trail) {
$trail->parent('admin.dashboard');

View File

@@ -1,5 +1,6 @@
<?php
use \App\Notifications\sms;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
/*
|--------------------------------------------------------------------------
@@ -29,9 +30,7 @@ Route::get('/picture/{id}', 'PictureController@show');
Route::get('/pictures', 'PictureController@index');
Route::get('/file/get','GoogleDriveController@getFile')->middleware('fileperm:file,r');
Route::get('/test','GoogleDriveController@list');
@
Route::middleware(['auth'])->name('admin.')->group(function () {
/* Espace Administration Route */
@@ -160,6 +159,7 @@ Route::middleware(['auth'])->name('admin.')->group(function () {
Route::get('/admin/profil/avatar' , 'UserController@UserAvatar')->name('profil.avatar');
Route::get('/admin/profil/password' , 'UserController@UserPassword')->name('profil.psw');
Route::get('/admin/profil/adress' , 'UserController@UserAdress')->name('profil.adress');
Route::get('/admin/profil/notifications','UserController@userNotification')->name('profil.notifications');
Route::post('/admin/profil/edit/adress' , 'UserController@editUserAdress');
Route::post('/admin/profil/edit/password' , 'UserController@editUserPassword');
Route::get('/admin/profil/edit/avatar/{id}' , 'UserController@editUserAvatar');

3
webpack.mix.js vendored
View File

@@ -11,6 +11,7 @@ let mix = require('laravel-mix');
|
*/
mix.sass('resources/assets/sass/app.scss', 'public/css')
mix.js('resources/assets/js/bootstrap.js','public/js').sourceMaps()
.sass('resources/assets/sass/app.scss', 'public/css')
.sass('resources/theme/material-dashboard/assets/scss/material-dashboard.scss', 'public/css')
.styles('resources/custom.css','public/css/custom.css');