FEATURE #1552 @1h: save sent messages into database

This commit is contained in:
Michal Kváček
2017-09-14 20:18:32 +02:00
parent 6b0509a1db
commit b1b31afa3b
15 changed files with 266 additions and 36 deletions
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSentEmailsTable extends Migration
{
/**
* Run migration
*/
public function up()
{
Schema::create('sent_emails', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('subject');
$table->string('from');
$table->string('to');
$table->text('message');
$table->boolean('is_new')->default(true)->commect('Was this message read (in admin)?');
});
}
/**
* Rollback migration
*/
public function down()
{
Schema::dropIfExists('sent_emails');
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Modules\ContactForm\Entities;
use Illuminate\Database\Eloquent\Model;
class SentEmail extends Model
{
protected $fillable = [
'from',
'to',
'subject',
'message'
];
protected $casts = ['is_new' => 'boolean'];
}
+12 -14
View File
@@ -1,13 +1,14 @@
<?php <?php
namespace Modules\ContactForm\Handlers; namespace Modules\ContactForm\Handlers;
use App\CMS\Contracts\Content\AdvancedContentModifier; use App\CMS\Contracts\Content\AdvancedContentModifier;
use App\CMS\Contracts\Content\ContentTitles; use App\CMS\Contracts\Content\ContentTitles;
use App\CMS\Enumerations\ModulesHandlerToId; use App\CMS\Enumerations\ModulesHandlerToId;
use App\CMS\Handlers\AdminHandler; use App\CMS\Handlers\AdminHandler;
use App\Http\Requests\Request;
use App\Models\Content\Content; use App\Models\Content\Content;
use App\Models\User; use App\Models\User;
use Modules\ContactForm\Entities\SentEmail;
class ContactForm extends AdminHandler implements ContentTitles, AdvancedContentModifier class ContactForm extends AdminHandler implements ContentTitles, AdvancedContentModifier
{ {
@@ -27,7 +28,6 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Getter for section names in creating/editing content resource * Getter for section names in creating/editing content resource
*
* @return mixed * @return mixed
*/ */
public static function getExtendedFormSections() public static function getExtendedFormSections()
@@ -40,9 +40,7 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Getter for views used in extended part of form for creating new content * Getter for views used in extended part of form for creating new content
*
* This method should return pairs <section, view-name>. View is returned only as name in plain text * This method should return pairs <section, view-name>. View is returned only as name in plain text
*
* @return array of views/templates/html codes divided into section * @return array of views/templates/html codes divided into section
*/ */
public static function getExtendedFormInputsCreate() public static function getExtendedFormInputsCreate()
@@ -64,7 +62,6 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Register admin menu (or multiple ones) * Register admin menu (or multiple ones)
*
* This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before * This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before
* starting any middleware.. * starting any middleware..
* *
@@ -77,15 +74,21 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
$submenu = $menu->whereTitle(trans('admin/mainMenu.contentPages')); $submenu = $menu->whereTitle(trans('admin/mainMenu.contentPages'));
$submenu->dropdown(trans('contactform::admin/adminMenu.contactForm'), function ($submenu) use ($user) { $submenu->dropdown(trans('contactform::admin/adminMenu.contactForm'), function ($submenu) use ($user) {
$submenu->route('content.new', trans('contactform::admin/adminMenu.new'), ['moduleId' => self::getModuleId()], 10, ['icon' => 'fa fa-plus']); $submenu->route('content.new', trans('contactform::admin/adminMenu.new'), ['module' => config('contactform.alias')], 10, ['icon' => 'fa fa-plus']);
$submenu->route('content.overview', trans('contactform::admin/adminMenu.overview'), ['moduleId' => self::getModuleId()], 20, ['icon' => 'fa fa-list']); $submenu->route('content.overview', trans('contactform::admin/adminMenu.overview'), ['module' => config('contactform.alias')], 20, ['icon' => 'fa fa-list']);
// $submenu->route('emails.sent', trans('contactform::admin/adminMenu.sentMessages'), [], 30, ['icon' => 'fa fa-send']);
}, 25, ['icon' => 'fa fa-envelope-o']); }, 25, ['icon' => 'fa fa-envelope-o']);
$new = SentEmail::where('is_new', true)->count();
$suffix = ($new == 0) ? '' : ' ('.$new.')';
$menu->route('sentEmails.index', trans('contactform::admin/adminMenu.sentMessages'). $suffix , [], 50, ['icon' => 'fa fa-send']);
} }
/** /**
* Does given module manage content? Or is it just module with widgets/something internal/something absolutely else? * Does given module manage content? Or is it just module with widgets/something internal/something absolutely else?
*
* @return bool * @return bool
*/ */
public static function managesContent() public static function managesContent()
@@ -95,9 +98,7 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Get translated title for pages overview of given type. * Get translated title for pages overview of given type.
*
* This value is used for rendering list of all content pages of given type in administration. * This value is used for rendering list of all content pages of given type in administration.
*
* @return string * @return string
*/ */
public static function getOverviewTitle() public static function getOverviewTitle()
@@ -107,7 +108,6 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Title displayed above for for creating new content page * Title displayed above for for creating new content page
*
* @return string * @return string
*/ */
public static function getCreateNewTitle() public static function getCreateNewTitle()
@@ -129,7 +129,6 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Does this module support categories? * Does this module support categories?
*
* @return boolean * @return boolean
*/ */
public static function supportCategories() public static function supportCategories()
@@ -139,7 +138,6 @@ class ContactForm extends AdminHandler implements ContentTitles, AdvancedContent
/** /**
* Method called right after content page is marked as deleted * Method called right after content page is marked as deleted
*
* This method is supposed to clean after "deleted" page. * This method is supposed to clean after "deleted" page.
* *
* @param Content $content * @param Content $content
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Modules\ContactForm\Http\Controllers\Admin;
use App\Http\Controllers\Admin\Controller;
use Modules\ContactForm\Entities\SentEmail;
class SentEmails extends Controller
{
public function index()
{
$emails = SentEmail::orderBy('created_at', 'desc')
->paginate();
return view('contactform::admin.sent', compact('emails'));
}
public function show(SentEmail $email)
{
if ($email->is_new) {
$email->is_new = false;
$email->save();
}
return view('contactform::admin.emailDetail', compact('email'));
}
}
+10 -15
View File
@@ -1,12 +1,13 @@
<?php <?php
namespace Modules\ContactForm\Http\Controllers\Visitor; namespace Modules\ContactForm\Http\Controllers\Visitor;
use App\CMS\Helpers\Template; use App\CMS\Helpers\Template;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Content\Content; use App\Models\Content\Content;
use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Modules\ContactForm\Http\Requests\SendNewEmailRequest; use Modules\ContactForm\Http\Requests\SendNewEmailRequest;
use Modules\ContactForm\Mail\ContactFormMessage;
class CreateNewMessage extends Controller class CreateNewMessage extends Controller
{ {
@@ -26,35 +27,29 @@ class CreateNewMessage extends Controller
// select template // select template
$template = isset($form->moduleSettings['emailTemplate']) ? $form->moduleSettings['emailTemplate'] : 'contactform::emails.default'; $template = isset($form->moduleSettings['emailTemplate']) ? $form->moduleSettings['emailTemplate'] : 'contactform::emails.default';
$subject = isset($form->moduleSettings['subject']) ? $form->moduleSettings['subject'] : trans('contactform::admin/contents.defaultSubject');
$data = $request->except('_token', 'g-recaptcha-response');
// send email Mail::to($form->moduleSettings['contactEmail'])
$status = Mail::send(Template::name($template), ['data' => $request], function (Message $message) use ($request, $form) { ->send(new ContactFormMessage($data, $subject, Template::name($template)));
$message->from($request->email, $request->name);
// get message subject
$subject = isset($form->moduleSettings['subject']) ? $form->moduleSettings['subject'] : trans('contactform::admin/contents.defaultSubject');
$message->to($form->moduleSettings['email'])
->subject($subject);
});
// inform user about success or failure // inform user about success or failure
return $this->sendResponse($status, $request, $form); return $this->sendResponse($request, $form);
} }
private function sendResponse($status, SendNewEmailRequest $request, $form) private function sendResponse(SendNewEmailRequest $request, $form)
{ {
// send response for ajax // send response for ajax
if ($request->ajax()) { if ($request->ajax()) {
return response()->json([ return response()->json([
'status' => $status ? 'success' : 'failed', 'status' => 'success',
'redirectUrl' => $form->url 'redirectUrl' => $form->url
]); ]);
} else { } else {
// redirect user to previous form // redirect user to previous form
$response = redirect()->back(); $response = redirect()->back();
return $status ? $response->with('success', 'sent') : $response->with('error', 'cannotSend'); return $response->with('success', 'sent');
} }
} }
} }
-1
View File
@@ -6,7 +6,6 @@ class SendNewEmailRequest extends Request
{ {
/** /**
* Get the validation rules that apply to the request. * Get the validation rules that apply to the request.
*
* @return array * @return array
*/ */
public function rules() public function rules()
+12
View File
@@ -9,4 +9,16 @@ Route::group([
Route::post('/message/{formId}', 'CreateNewMessage@postMessage') Route::post('/message/{formId}', 'CreateNewMessage@postMessage')
->name('email.send'); ->name('email.send');
});
Route::group([
'middleware' => ['admin', 'bindings'],
'namespace' => '\Modules\ContactForm\Http\Controllers\Admin',
'prefix' => LaravelLocalization::setLocale() . '/contactform'
], function () {
Route::get('sent', 'SentEmails@index')
->name('sentEmails.index');
Route::get('send/{email}', 'SentEmails@show')->name('sentEmails.show');
}); });
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace Modules\ContactForm\Listeners;
use Modules\ContactForm\Entities\SentEmail;
class SaveSentEmail
{
public function handle(\Illuminate\Mail\Events\MessageSending $event)
{
$email = $event->message;
$from = key($email->getFrom());
$to = key($email->getTo());
SentEmail::create([
'from' => $from,
'to' => $to,
'subject' => $email->getSubject(),
'message' => $email->getBody()
]);
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace Modules\ContactForm\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ContactFormMessage extends Mailable
{
use Queueable, SerializesModels;
protected $data;
/**
* @var
*/
private $template;
/**
* Create a new message instance.
*
* @param $data
* @param $template
*/
public function __construct($data, $subject, $template)
{
$this->data = $data;
$this->template = $template;
$this->subject = $subject;
}
/**
* Build the message.
* @return $this
*/
public function build()
{
return $this->subject($this->subject)
->from($this->data['email'])
->view($this->template, ['data' => $this->data]);
}
}
+1
View File
@@ -28,6 +28,7 @@ class ContactFormServiceProvider extends ServiceProvider
*/ */
public function register() public function register()
{ {
$this->app->register(EventServiceProvider::class);
} }
private function registerWidgets() private function registerWidgets()
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Modules\ContactForm\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
\Illuminate\Mail\Events\MessageSending::class => [
\Modules\ContactForm\Listeners\SaveSentEmail::class
],
];
}
+6 -6
View File
@@ -1,9 +1,9 @@
<?php <?php
return [ return [
"contactForm" => "Kontaktní formulář", "contactForm" => "Kontaktní formulář",
"emails" => "E-mailové šablony", "emails" => "E-mailové šablony",
"new" => "Nový", "new" => "Nový",
"overview" => "Všechny formuláře", "overview" => "Všechny formuláře",
"sentMessages" => "Zprávy", "sentMessages" => "Přijaté zprávy",
"templatePath" => "Kontaktní formulář", "templatePath" => "Kontaktní formulář",
]; ];
+9
View File
@@ -0,0 +1,9 @@
<?php
return [
'from' => 'Od',
'to' => 'Komu',
'subject' => 'Předmět',
'createdAt' => 'Odesláno',
'overview' => 'Přehled přijatých e-mailů',
'detail' => 'Detail e-mailu'
];
@@ -0,0 +1,21 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', @trans('contactform::sent.detail'))
@section('headerButtons')
<a class="btn btn-secondary btn-sm rounded" href="{{route('sentEmails.index')}}"><i class="fa fa-list"></i></a>
@endsection
@section('content')
<div class="card items">
<div class="card-block">
<h2>{{$email->subject}}</h2>
<p>
{{$email->message}}
</p>
</div>
<div class="card-footer">
</div>
</div>
@endsection
+42
View File
@@ -0,0 +1,42 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', @trans('contactform::sent.overview'))
@section('content')
@if (count($emails))
<div class="card items">
<div class="card-block">
<table class="table table-striped full-width">
<tr>
<th>@lang('contactform::sent.from')</th>
<th>@lang('contactform::sent.to')</th>
<th>@lang('contactform::sent.createdAt')</th>
<th>@lang('contactform::sent.subject')</th>
<th></th>
</tr>
@foreach($emails as $email)
<tr @if ($email->is_new) class="bold" @endif >
<td>{{$email->from}}</td>
<td>{{$email->to}}</td>
<td>@date($email->created_at)</td>
<td>{{$email->subject}}</td>
<td>
<a href="{{route('sentEmails.show', compact('email'))}}" class="btn btn-sm rounded btn-secondary">
<i class="fa fa-eye"></i>
</a>
</td>
</tr>
@endforeach
</table>
</div>
<div class="card-footer">
{!! $emails->render() !!}
</div>
</div>
@else
<div class="alert alert-info">
<em>@lang('contactform::sent.noEntries')</em>
</div>
@endif
@stop