Merge branch 'fix/notification' into 'master'

Fix/notification

See merge request CIEFWorldwideSdnBhd/exchange!121
This commit is contained in:
Jack Goh
2018-08-16 09:58:11 +00:00
21 changed files with 248 additions and 155 deletions
-5
View File
@@ -13,11 +13,6 @@ DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\Rate;
class RateUpdated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $rate;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Rate $rate)
{
$this->rate = $rate;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('rate-updated');
//return new PrivateChannel('rate-updated');
}
public function broadcastWith() {
return [
'rate' => $this->rate,
];
}
}
+19 -44
View File
@@ -25,11 +25,13 @@ class BookingController extends Controller
$user = Auth::user();
$bookings = Booking::select('user_id', 'id', 'created_at', 'status', 'rate', 'term', 'amount', 'bia', 'verification_status')
->where('user_id', Auth::user()->id)
->where('status', '=', '6')
->orwhere('status', '=', '4')
->orwhere('status', '=', '3')
->orwhere('status', '=', '2')
->orwhere('status', '=', '1')
->where(function ($query) {
$query->where('status', '=', '6')
->orwhere('status', '=', '4')
->orwhere('status', '=', '3')
->orwhere('status', '=', '2')
->orwhere('status', '=', '1');
})
->orderby('updated_at','desc')
->paginate(10);
@@ -159,14 +161,13 @@ class BookingController extends Controller
public function adminIndex(){
$user = Auth::user();
$bookings = Booking::select('user_id', 'id', 'created_at', 'admin_status', 'rate', 'term', 'amount', 'bia', 'verification_status')
->where('admin_status', '=', '5')
->orwhere('admin_status', '=', '4')
->orwhere('admin_status', '=', '3')
->orwhere('admin_status', '=', '2')
->orwhere('admin_status', '=', '1')
->orderby('updated_at','desc')
->paginate(10);
->where('admin_status', '=', '5')
->orwhere('admin_status', '=', '4')
->orwhere('admin_status', '=', '3')
->orwhere('admin_status', '=', '2')
->orwhere('admin_status', '=', '1')
->orderby('updated_at','desc')
->paginate(10);
// reformat to fit frontend structure
foreach ($bookings as $booking) {
@@ -623,16 +624,9 @@ class BookingController extends Controller
$booking->admin_status = 2;
$booking->save();
// Add notification message to admin
$adminNotification = new Notification;
$adminNotification->detail = "A bankslip is uploaded for booking " . $booking->id;
$adminNotification->link = "/booking/" . $booking->id . "/verification";
$adminNotification->user_id = User::withRole('admin')->first()->id;
$adminNotification->save();
$user_bankslip->transfer_amount = $request->input('transfer_amount');
$user_bankslip->save();
return response()->json($adminNotification,200);
return response()->json(["success"=>true],200);
}
public function uploadPurchaseOrder(Request $request, $id)
@@ -854,21 +848,13 @@ class BookingController extends Controller
$booking->status = 4;
if($booking->term !== "x1_ba" || $booking->term !== "x2_cheque"){
$booking->admin_status = 3;
// Add notification message to user
$userNotification = new Notification;
$userNotification->detail = "Your bankslip for booking " . $booking->id . " is approved.";
$userNotification->link = "/booking/" . $booking->id . "/transfer";
$userNotification->user_id = $booking->user_id;
$userNotification->save();
// TODO : Add notification message to user
}
else{
$booking->admin_status = 5;
// Add notification message to user
$userNotification = new Notification;
$userNotification->detail = "Your bankslip for booking " . $booking->id . " is approved.";
$userNotification->link = "/booking/" . $booking->id . "/supplier";
$userNotification->user_id = $booking->user_id;
$userNotification->save();
// TODO : Add notification message to user
}
$booking->save();
@@ -988,12 +974,6 @@ class BookingController extends Controller
$booking->admin_status = 6; // upload invoice
$booking->save();
$adminNotification = new Notification;
$adminNotification->detail = "Purchase Order for booking " . $booking->id . " is uploaded.";
$adminNotification->link = "/booking/" . $booking->id . "/upload-invoice";
$adminNotification->user_id = User::withRole('admin')->first()->id;
$adminNotification->save();
return response()->json($purchase_order,200);
}
@@ -1011,11 +991,6 @@ class BookingController extends Controller
$booking->admin_status = 7; // completed
if($booking->save()){
$adminNotification = new Notification;
$adminNotification->detail = "Invoice for booking " . $booking->id . " is uploaded.";
$adminNotification->link = "/booking/" . $booking->id . "/complete";
$adminNotification->user_id = $booking->user_id;
$adminNotification->save();
return response()->json(['message'=>"Success"],200);
}
}
@@ -5,7 +5,6 @@ namespace App\Http\Controllers;
use App\ChinaBankSlip;
use App\Booking;
use App\User;
use App\Notification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Validator;
@@ -82,13 +81,6 @@ class ChinaBankSlipController extends Controller
$booking->admin_status = 6;
$booking->save();
$userNotification = new Notification;
$userNotification->detail = "Your china bankslip for booking " . $booking->id . " is uploaded.";
$userNotification->link = "/booking/" . $booking->id . "/upload-po";
$userNotification->user_id = $booking->user_id;
$userNotification->save();
return response()->json(["message"=> "Success"],200);
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Observers;
use App\Rate;
use App\User;
use App\Events\RateUpdated;
class RateObserver
{
/**
* Handle the rate "created" event.
*
* @param \App\Rate $rate
* @return void
*/
public function created(Rate $rate)
{
event(new RateUpdated($rate));
}
}
+3
View File
@@ -5,6 +5,8 @@ namespace App\Providers;
use Laravel\Dusk\DuskServiceProvider;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use App\Observers\RateObserver;
use App\Rate;
class AppServiceProvider extends ServiceProvider
@@ -21,6 +23,7 @@ class AppServiceProvider extends ServiceProvider
Schema::defaultStringLength(191);
}
*/
Rate::observe(RateObserver::class);
Schema::defaultStringLength(191);
}
+2 -1
View File
@@ -14,7 +14,8 @@ class BroadcastServiceProvider extends ServiceProvider
*/
public function boot()
{
Broadcast::routes();
//Broadcast::routes();
Broadcast::routes(["middleware" => ["auth:api"]]);
require base_path('routes/channels.php');
}
+1
View File
@@ -13,6 +13,7 @@
"laravel/socialite": "^3.0",
"laravel/tinker": "~1.0",
"laravelcollective/html": "^5.6",
"pusher/pusher-php-server": "~3.0",
"tymon/jwt-auth": "^1.0.0-rc.2",
"zizaco/entrust": "dev-master"
},
+1 -1
View File
@@ -165,7 +165,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,
+2 -1
View File
@@ -36,7 +36,8 @@ return [
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
//
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
],
],
@@ -0,0 +1,28 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DropNotificationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::dropIfExists('notifications');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
@@ -0,0 +1,35 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateNotificationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('notifications', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('type');
$table->morphs('notifiable');
$table->text('data');
$table->timestamp('read_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('notifications');
}
}
-1
View File
@@ -28,7 +28,6 @@ class DatabaseSeeder extends Seeder
$this->call(SettingActiveBankSeeder::class);
$this->call(SettingTaxRateSeeder::class);
$this->call(SettingBillingChargeSeeder::class);
$this->call(NotificationSeeder::class);
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
}
-35
View File
@@ -1,35 +0,0 @@
<?php
use Illuminate\Database\Seeder;
use App\User;
use Carbon\Carbon;
class NotificationSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$user = User::where("email", "user@example.com")->first();
$admin = User::where("email", "admin@example.com")->first();
DB::table('notifications')->insert([
'detail' => 'This is an user seeder notification',
'user_id' => $user->id,
'link' => '/',
'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
]);
DB::table('notifications')->insert([
'detail' => 'This is an admin seeder notification',
'user_id' => $admin->id,
'link' => '/',
'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
]);
}
}
+2
View File
@@ -24,8 +24,10 @@
"element-ui": "^2.4.4",
"jquery": "^3.3.1",
"js-cookie": "^2.2.0",
"laravel-echo": "^1.4.0",
"npm": "^6.0.1",
"popper.js": "^1.14.1",
"pusher-js": "^4.3.0",
"sweetalert2": "^7.15.1",
"vform": "^1.0.0",
"vue": "^2.5.16",
@@ -210,6 +210,7 @@ export default {
})
},
}
}
+45 -50
View File
@@ -6,7 +6,7 @@
</router-link>
<template v-if="user">
<el-dropdown trigger="click" align="right">
<!-- <el-dropdown trigger="click" align="right">
<el-badge :value="bellBadge > 0 ? bellBadge : ''" class="item">
<el-button icon="el-icon-bell" circle @click="refreshNoti()"></el-button>
</el-badge>
@@ -32,7 +32,7 @@
<el-button v-if="pagination.next_page_url != null" id="notification-load-more" v-on:click='fetchPaginateBooking(pagination.next_page_url)'>Load more</el-button>
<div v-else id="notification-load-more"></div>
</el-dropdown-menu>
</el-dropdown>
</el-dropdown> -->
</template>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggler" aria-controls="navbarToggler" aria-expanded="false">
@@ -98,8 +98,8 @@ export default {
data: () => ({
appName: window.config.appName,
notification:[],
loadingNotification:false,
//notification:[],
//loadingNotification:false,
bellBadge : 0,
unread_message_length:0,
url: '/api/notification/user',
@@ -108,11 +108,6 @@ export default {
computed: mapGetters({
user: 'auth/user'
}),
mounted(){
if(this.user){
this.getNotification(this.url)
}
},
methods: {
async logout(){
// Log out the user.
@@ -121,33 +116,33 @@ export default {
// Redirect to login.
this.$router.push({ name: 'login' });
},
refreshNoti() {
axios.get(this.url).then(response => {
this.bookingTable = response.data.data
this.notification = response.data.message.data;
this.bellBadge = response.data.unread_message.length;
this.makePagination(response.data.message);
console.log(response.data);
})
},
getNotification(url){
this.notification = [];
this.loadingNotification=true;
axios
.get(url)
.then((response) => {
this.loadingNotification=false;
this.notification = response.data.message.data;
this.bellBadge = response.data.unread_message.length;
this.makePagination(response.data.message);
console.log(response.data);
}).catch((error) => {
console.log(error)
this.$router.push({
name: 'notfound'
})
})
},
// refreshNoti() {
// axios.get(this.url).then(response => {
// this.bookingTable = response.data.data
// this.notification = response.data.message.data;
// this.bellBadge = response.data.unread_message.length;
// this.makePagination(response.data.message);
// console.log(response.data);
// })
// },
// getNotification(url){
// this.notification = [];
// this.loadingNotification=true;
// axios
// .get(url)
// .then((response) => {
// this.loadingNotification=false;
// this.notification = response.data.message.data;
// this.bellBadge = response.data.unread_message.length;
// this.makePagination(response.data.message);
// console.log(response.data);
// }).catch((error) => {
// console.log(error)
// this.$router.push({
// name: 'notfound'
// })
// })
// },
makePagination(data){
let pagination ={
current_page: data.current_page,
@@ -159,7 +154,7 @@ export default {
},
fetchPaginateBooking(url) {
this.url = url;
this.loadingNotification=true;
//this.loadingNotification=true;
if(this.url !== null){
axios
.get(url)
@@ -177,21 +172,21 @@ export default {
})
}
},
readNotification(notification_id){
axios
.post('/api/notification/read-notification/'+notification_id)
.then((response) => {
this.getNotification(this.url);
}).catch((error) => {
console.log(error)
this.$router.push({
name: 'notfound'
})
})
},
// readNotification(notification_id){
// axios
// .post('/api/notification/read-notification/'+notification_id)
// .then((response) => {
// this.getNotification(this.url);
// }).catch((error) => {
// console.log(error)
// this.$router.push({
// name: 'notfound'
// })
// })
// },
navigateTo(nav) {
window.location.href = nav;
}
}
}
}
</script>
-1
View File
@@ -1,7 +1,6 @@
import store from '~/store'
export default (to, from, next) => {
console.log(store.getters['auth/role'])
if (store.getters['auth/role'] !== 'admin') {
next({ name: 'home' })
} else {
+33
View File
@@ -402,6 +402,8 @@ import Form from 'vform'
import LoginWithGithub from '~/components/LoginWithGithub'
import store from '~/store'
import axios from 'axios'
import Echo from "laravel-echo"
import Pusher from "pusher-js"
export default {
middleware: ['auth'],
@@ -526,8 +528,39 @@ export default {
this.initBooking();
this.getRate();
this.getCompleteBooking();
this.listen();
},
methods: {
// listen to update rate changes
listen(){
window.Echo = new Echo({
broadcaster: 'pusher',
key: '20cae353616471c0c765',
cluster: 'ap1',
encrypted: true,
auth: {
headers: {
Authorization: 'Bearer ' + localStorage.getItem("token")
},
},
});
window.Echo.channel('rate-updated')
.listen('RateUpdated', response => {
if (! ('Notification' in window)) {
alert('Web Notification is not supported');
return;
}
this.$message({
showClose: true,
message: 'New rate updated at ' + response.rate.created_at,
duration: 20000
});
this.rate = response.rate
});
},
getBooking(){
let $this = this
axios.get(this.url).then(response => {
+7 -7
View File
@@ -49,8 +49,8 @@ Route::group(['middleware' => 'auth:api'], function () {
Route::patch('settings/profile', 'Settings\ProfileController@update');
Route::patch('settings/password', 'Settings\PasswordController@update');
Route::get('notification/user', 'NotificationController@getUserMessage');
Route::post('notification/read-notification/{notification_id}', 'NotificationController@readNotification');
//Route::get('notification/user', 'NotificationController@getUserMessage');
//Route::post('notification/read-notification/{notification_id}', 'NotificationController@readNotification');
// for both user and admin
Route::get('active-bank', 'SettingActiveBankController@index');
@@ -115,11 +115,11 @@ Route::group(['middleware' => ['role:admin']], function() {
Route::put('supplier-booking/{id}', 'BookingSupplierController@update');
Route::post('booking/{id}/confirm-supplier', 'BookingController@confirmSupplier');
Route::get('notification', 'NotificationController@index');
Route::get('notification/{notification}', 'NotificationController@show');
Route::post('notification', 'NotificationController@store');
Route::put('notification/{notification}', 'NotificationController@update');
Route::delete('notification/{notification}', 'NotificationController@delete');
// Route::get('notification', 'NotificationController@index');
// Route::get('notification/{notification}', 'NotificationController@show');
// Route::post('notification', 'NotificationController@store');
// Route::put('notification/{notification}', 'NotificationController@update');
// Route::delete('notification/{notification}', 'NotificationController@delete');
Route::post('booking/{id}/upload-china-bankslip','ChinaBankSlipController@store');
Route::patch('booking/{id}/update-china-bankslip','ChinaBankSlipController@update');
+1 -1
View File
@@ -12,5 +12,5 @@
*/
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
return true;
});