notifications ready

This commit is contained in:
merdan 2022-11-21 09:54:10 +05:00
parent 5d3a765882
commit c405e993b5
17 changed files with 476 additions and 1 deletions

View File

@ -28,5 +28,11 @@ return [
'route' => 'admin.catalog.menus.index', 'route' => 'admin.catalog.menus.index',
'sort' => 7, 'sort' => 7,
'icon-class' => '', 'icon-class' => '',
],[
'key' => 'marketing.push-notification',
'name' => 'Push notifications',
'route' => 'admin.push.index',
'sort' => 3,
'icon-class' => '',
], ],
]; ];

View File

@ -0,0 +1,8 @@
<?php
return [
'push' => [
'url'=> env('PUSH_URL', ' https://fcm.googleapis.com/fcm/send'),
'token' => env('PUSH_TOKEN','key=AAAA9LHgcmM:APA91bHkC0wGvNhfoD6UlzUsSilSnhAghY27PNpCwbte4AG0zN2LTnbxVtgcU4q5hwPUfcJuAiL00Ioh2XCEasDW6GYs9IZR4MbbholyASABU6aoQjq95aGpuwci-z_oD2-p1m7COwcO')
]
];

View File

@ -0,0 +1,78 @@
<?php
namespace Sarga\Admin\DataGrids;
use Illuminate\Support\Facades\DB;
use Webkul\Ui\DataGrid\DataGrid;
class NotificationDataGrid extends DataGrid
{
protected $index = 'id';
protected $sortOrder = 'desc';
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('marketing_notifications')
->addSelect('id','title','content','last_sent_at','updated_at');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$this->addColumn([
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'title',
'label' => 'Title',
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'content',
'label' => "Content",
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'last_sent_at',
'label' => 'Last sent at',
'type' => 'datetime',
'searchable' => false,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'updated_at',
'label' => 'Updated at',
'type' => 'datetime',
'searchable' => false,
'sortable' => true,
'filterable' => true,
]);
}
public function prepareActions()
{
$this->addAction([
'title' => trans('admin::app.datagrid.edit'),
'method' => 'GET',
'route' => 'admin.notifications.edit',
'icon' => 'icon pencil-lg-icon',
]);
}
}

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMarketingNotificationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('marketing_notifications', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('content');
$table->dateTime('last_sent_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('marketing_notifications');
}
}

View File

@ -0,0 +1,85 @@
<?php
namespace Sarga\Admin\Http\Controllers;
use Illuminate\Routing\Controller;
use Sarga\Admin\Http\Firebase;
use Sarga\Shop\Repositories\NotificationRepository;
class PushController extends Controller
{
public function __construct(protected NotificationRepository $notificationRepository)
{
$this->_config = request('_config');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\View\View
*/
public function index()
{
return view($this->_config['view']);
}
/**
* Show the view for the specified resource.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function edit($id)
{
$notification = $this->notificationRepository->findOrFail($id);
return view($this->_config['view'],compact('notification'));
}
/**
* Show the form for creating a new resource.
*
* @param int $orderId
* @return \Illuminate\View\View
*/
public function create()
{
return view($this->_config['view']);
}
/**
* Store a newly created resource in storage.
*
* @param int $orderId
* @return \Illuminate\Http\Response
*/
public function store()
{
$this->validate(request(),[
'title' => 'required|max:500',
'content' => 'required|max:3000'
]);
if($note = $this->notificationRepository->create(request()->all())){
$this->sendNotification($note);
return redirect()->route($this->_config['redirect']);
}else {
session()->flash('error', trans('Error on creating notification'));
return redirect()->back();
}
}
private function sendNotification($note){
try {
$data = $note->only(['id','title','content'])+['type'=>'topic'];
(new Firebase('/topics/notifications',$data))->send();
session()->flash('success', trans('Notification sent successfully'));
}catch (\Exception $ex){
report($ex);
session()->flash('error', trans('Notification does not sent'));
}
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace Sarga\Admin\Http;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class Firebase
{
public $data;
public $priority;
public $notification;
public $to;
public function __construct($to,$content,$priority = 'high')
{
$this->data = [
'click_action' => 'FLUTTER_NOTIFICATION_CLICK',
] + $content;
$this->notification = [
'sound' => 'default',
'title' => $content['title'],
'body' =>$content['content']
];
$this->to = $to;
$this->priority = $priority;
}
public function send(){
$body = json_encode((object)$this);
$response = Http::withHeaders([
'Authorization' => config('notification.push.token'),
'Content-Type' => 'application/json'
])->withBody($body,'application/json')
->timeout(30)
->post(config('notification.push.url'));
if($response->failed())
{
Log::error($response);
$response->throw();
}
}
}

View File

@ -28,6 +28,8 @@ class AdminServiceProvider extends ServiceProvider
__DIR__ . '/../Resources/views/customers/edit.blade.php' => resource_path('views/vendor/admin/customers/edit.blade.php'), __DIR__ . '/../Resources/views/customers/edit.blade.php' => resource_path('views/vendor/admin/customers/edit.blade.php'),
],'admin'); ],'admin');
$this->publishes([ __DIR__ . '/../Config/push.php','config/push.php'],'sarga_config');
$this->app->register(EventServiceProvider::class); $this->app->register(EventServiceProvider::class);
} }

View File

@ -0,0 +1,53 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('Add notifications') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.push.store') }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = '{{ route('admin.push.index') }}'"></i>
{{ __('Add notification') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('Send') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<accordian :title="'{{ __('admin::app.marketing.templates.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('title') ? 'has-error' : '']">
<label for="title" class="required">{{ __('Title') }}</label>
<input v-validate="'required'" class="control" id="title" name="title" value="{{ old('title') }}" data-vv-as="&quot;{{ __('Title') }}&quot;"/>
<span class="control-error" v-if="errors.has('title')">@{{ errors.first('title') }}</span>
</div>
<div class="control-group" :class="[errors.has('content') ? 'has-error' : '']">
<label for="content" class="required">{{ __('admin::app.marketing.templates.content') }}</label>
<textarea v-validate="'required'" class="control" id="content" name="content" data-vv-as="&quot;{{ __('admin::app.marketing.templates.content') }}&quot;">{{ old('content') }}</textarea>
<span class="control-error" v-if="errors.has('content')">@{{ errors.first('content') }}</span>
</div>
</div>
</accordian>
</div>
</div>
</form>
</div>
@stop

View File

@ -0,0 +1,26 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('Notification Messages') }}
@stop
@section('content')
<div class="content">
<div class="page-header">
<div class="page-title">
<h1>{{ __('Notification Messages') }}</h1>
</div>
<div class="page-action">
<a href="{{ route('admin.push.create') }}" class="btn btn-lg btn-primary">
{{ __('Add notification') }}
</a>
</div>
</div>
<div class="page-content">
@inject('notificationGrid','Sarga\Admin\DataGrids\NotificationDataGrid')
{!! $notificationGrid->render() !!}
</div>
</div>
@endsection

View File

@ -0,0 +1,51 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('Edit notification Message') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.push.store') }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="window.location = '{{ route('admin.push.index') }}'"></i>
{{ __('Edit notification') }}
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('Send') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<accordian :title="'{{ __('admin::app.marketing.templates.general') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('title') ? 'has-error' : '']">
<label for="title" class="required">{{ __('Title max: 500') }}</label>
<input v-validate="'required'" class="control" id="title" name="title" value="{{ old('title')?:$notification->title }}" data-vv-as="&quot;{{ __('Title') }}&quot;"/>
<span class="control-error" v-if="errors.has('title')">@{{ errors.first('title') }}</span>
</div>
<div class="control-group" :class="[errors.has('content') ? 'has-error' : '']">
<label for="content" class="required">{{ __('admin::app.marketing.templates.content') }} (max:3000)</label>
<textarea v-validate="'required'" class="control" id="content" name="content" data-vv-as="&quot;{{ __('admin::app.marketing.templates.content') }}&quot;">{{ old('content')?:$notification->content }}</textarea>
<span class="control-error" v-if="errors.has('content')">@{{ errors.first('content') }}</span>
</div>
</div>
</accordian>
</div>
</div>
</form>
</div>
@endsection

View File

@ -10,5 +10,20 @@ Route::group(['middleware' => ['web', 'admin'], 'prefix' => config('app.admin_ur
Route::get('delete-notifications', [Notifications::class, 'deleteNotification'])->defaults('_config', [ Route::get('delete-notifications', [Notifications::class, 'deleteNotification'])->defaults('_config', [
'redirect' => 'admin.notification.index', 'redirect' => 'admin.notification.index',
])->name('admin.notification.delete-notification'); ])->name('admin.notification.delete-notification');
//Notifications
Route::get('push-notifications', [Notifications::class,'index'])->defaults('_config', [
'view' => 'sarga_admin::marketing.notification.index',
])->name('admin.push.index');
Route::get('push-notifications/create', [Notifications::class,'create'])->defaults('_config', [
'view' => 'sarga_admin::marketing.notification.create',
])->name('admin.push.create');
Route::post('push-notifications/create', [Notifications::class,'store'])->defaults('_config', [
'redirect' => 'sarga_admin.notifications.index',
])->name('admin.push.store');
Route::get('push-notifications/edit/{id}', [Notifications::class,'edit'])->defaults('_config', [
'view' => 'sarga_admin::marketing.notification.view',
])->name('admin.push.edit');
}); });

View File

@ -0,0 +1,8 @@
<?php
namespace Sarga\Shop\Contracts;
interface Notification
{
}

View File

@ -0,0 +1,24 @@
<?php
namespace Sarga\Shop\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Marketing\Contracts\Notification as NotificationContract;
class Notification extends Model implements NotificationContract
{
protected $table = 'marketing_notifications';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'title',
'content',
'last_send_at'
];
protected $dates = ['created_at','updated_at','last_sent_at'];
}

View File

@ -0,0 +1,8 @@
<?php
namespace Sarga\Shop\Models;
class NotificationProxy extends \Konekt\Concord\Proxies\ModelProxy
{
}

View File

@ -13,5 +13,6 @@ class ModuleServiceProvider extends CoreModuleServiceProvider
\Sarga\Shop\Models\MenuTranslation::class, \Sarga\Shop\Models\MenuTranslation::class,
\Sarga\Shop\Models\Order::class, \Sarga\Shop\Models\Order::class,
\Sarga\Shop\Models\Category::class, \Sarga\Shop\Models\Category::class,
\Sarga\Shop\Models\Notification::class,
]; ];
} }

View File

@ -80,7 +80,9 @@ class CategoryRepository extends WCategoryRepository
->where('display_mode','description_only'); ->where('display_mode','description_only');
if(request()->has('vendor')){ if(request()->has('vendor')){
$query->whereHas('vendors', function($q){
$q->where('id',request()->get('vendor'));
});
} }
return $query->get(); return $query->get();

View File

@ -0,0 +1,17 @@
<?php
namespace Sarga\Shop\Repositories;
use Sarga\Shop\Contracts\Notification;
use Webkul\Core\Eloquent\Repository;
class NotificationRepository extends Repository
{
public function model()
{
return Notification::class;
}
}