Auto reply
This commit is contained in:
@@ -16,4 +16,7 @@ DB_USERNAME=freescout
|
||||
DB_PASSWORD=XXX
|
||||
|
||||
# System FreeScout emails will be sent to admin from this email address using PHP's mail() function
|
||||
MAIL_FROM_ADDRESS=noreply@example.com
|
||||
MAIL_FROM_ADDRESS=noreply@example.com
|
||||
|
||||
# After how many days log records in activity_logs table will be removed
|
||||
#ACTIVITY_LOGGER_DELETE_RECORDS_OLDER_THAN_DAYS=30
|
||||
@@ -64,6 +64,7 @@ class FetchEmails extends Command
|
||||
public function handle()
|
||||
{
|
||||
$now = time();
|
||||
$successfully = true;
|
||||
Option::set('fetch_emails_last_run', $now);
|
||||
|
||||
// Get active mailboxes
|
||||
@@ -81,15 +82,19 @@ class FetchEmails extends Command
|
||||
|
||||
try {
|
||||
$this->fetch($mailbox);
|
||||
Option::set('fetch_emails_last_successful_run', $now);
|
||||
} catch (\Exception $e) {
|
||||
$successfully = false;
|
||||
$this->logError('Error: '.$e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')').')';
|
||||
}
|
||||
|
||||
// Middleware Terminate handler is not launched for commands,
|
||||
// so we need to run processing subscription events manually
|
||||
Subscription::processEvents();
|
||||
}
|
||||
|
||||
if ($successfully) {
|
||||
Option::set('fetch_emails_last_successful_run', $now);
|
||||
}
|
||||
|
||||
// Middleware Terminate handler is not launched for commands,
|
||||
// so we need to run processing subscription events manually
|
||||
Subscription::processEvents();
|
||||
}
|
||||
|
||||
public function fetch($mailbox)
|
||||
@@ -248,9 +253,25 @@ class FetchEmails extends Command
|
||||
$prev_message_id = $references[0];
|
||||
}
|
||||
if ($prev_message_id) {
|
||||
|
||||
$prev_thread_id = '';
|
||||
|
||||
// Customer replied to the email from user
|
||||
preg_match('/^'.\App\Mail\Mail::MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER."\-(\d+)\-/", $prev_message_id, $m);
|
||||
if (!empty($m[1])) {
|
||||
$prev_thread = Thread::find($m[1]);
|
||||
$prev_thread_id = $m[1];
|
||||
}
|
||||
|
||||
// Customer replied to the auto reply
|
||||
if (!$prev_thread_id) {
|
||||
preg_match('/^'.\App\Mail\Mail::MESSAGE_ID_PREFIX_AUTO_REPLY."\-(\d+)\-/", $prev_message_id, $m);
|
||||
if (!empty($m[1])) {
|
||||
$prev_thread_id = $m[1];
|
||||
}
|
||||
}
|
||||
|
||||
if ($prev_thread_id) {
|
||||
$prev_thread = Thread::find($prev_thread_id);
|
||||
}
|
||||
}
|
||||
if (!empty($prev_thread)) {
|
||||
@@ -348,6 +369,7 @@ class FetchEmails extends Command
|
||||
*/
|
||||
public function saveCustomerThread($mailbox_id, $message_id, $prev_thread, $from, $to, $cc, $bcc, $subject, $body, $attachments, $headers)
|
||||
{
|
||||
// Copy extra recipients to CC
|
||||
$cc = array_merge($cc, $to);
|
||||
|
||||
// Find conversation
|
||||
@@ -431,6 +453,7 @@ class FetchEmails extends Command
|
||||
*/
|
||||
public function saveUserThread($mailbox, $message_id, $prev_thread, $user_id, $to, $cc, $bcc, $body, $attachments, $headers)
|
||||
{
|
||||
// Copy extra recipients to CC
|
||||
$cc = array_merge($cc, $to);
|
||||
|
||||
$conversation = null;
|
||||
|
||||
@@ -203,7 +203,7 @@ class MailboxesController extends Controller
|
||||
$mailbox->fill($request->all());
|
||||
$mailbox->save();
|
||||
|
||||
\Session::flash('flash_success', __('Connection settings saved!'));
|
||||
\Session::flash('flash_success_floating', __('Connection settings saved!'));
|
||||
|
||||
return redirect()->route('mailboxes.connection', ['id' => $id]);
|
||||
}
|
||||
@@ -318,8 +318,47 @@ class MailboxesController extends Controller
|
||||
$mailbox = Mailbox::findOrFail($id);
|
||||
$this->authorize('update', $mailbox);
|
||||
|
||||
if (!$mailbox->auto_reply_subject) {
|
||||
$mailbox->auto_reply_subject = 'Re: {%subject%}';
|
||||
}
|
||||
|
||||
return view('mailboxes/auto_reply', [
|
||||
'mailbox' => $mailbox
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save auto reply settings.
|
||||
*/
|
||||
public function autoReplySave($id, Request $request)
|
||||
{
|
||||
$mailbox = Mailbox::findOrFail($id);
|
||||
|
||||
$this->authorize('update', $mailbox);
|
||||
|
||||
if ($request->auto_reply_enabled) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'auto_reply_subject' => 'required|string|max:128',
|
||||
'auto_reply_message' => 'required|string',
|
||||
]);
|
||||
$validator->setAttributeNames([
|
||||
'auto_reply_subject' => __('Subject'),
|
||||
'auto_reply_message' => __('Message')
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect()->route('mailboxes.auto_reply', ['id' => $id])
|
||||
->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox->fill($request->all());
|
||||
|
||||
$mailbox->save();
|
||||
|
||||
\Session::flash('flash_success_floating', __('Auto Reply status saved'));
|
||||
|
||||
return redirect()->route('mailboxes.auto_reply', ['id' => $id]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,17 +47,21 @@ class SecureController extends Controller
|
||||
|
||||
return $cols;
|
||||
}
|
||||
$names = ActivityLog::select('log_name')->distinct()->get()->pluck('log_name');
|
||||
|
||||
// No need to check permissions here, as they are checked in routing
|
||||
|
||||
$names = ActivityLog::select('log_name')->distinct()->pluck('log_name')->toArray();
|
||||
|
||||
$activities = [];
|
||||
$cols = [];
|
||||
$current_name = '';
|
||||
|
||||
$name = '';
|
||||
if (!empty($request->name)) {
|
||||
$activities = ActivityLog::inLog($request->name)->orderBy('created_at', 'desc')->get();
|
||||
$current_name = $request->name;
|
||||
$name = $request->name;
|
||||
} elseif (count($names)) {
|
||||
$activities = ActivityLog::inLog($names[0])->orderBy('created_at', 'desc')->get();
|
||||
$current_name = $names[0];
|
||||
$name = $names[0];
|
||||
}
|
||||
|
||||
$logs = [];
|
||||
@@ -89,7 +93,39 @@ class SecureController extends Controller
|
||||
$logs[] = $log;
|
||||
}
|
||||
|
||||
return view('secure/logs', ['logs' => $logs, 'names' => $names, 'current_name' => $current_name, 'cols' => $cols]);
|
||||
if (!in_array($name, $names)) {
|
||||
$names[] = $name;
|
||||
}
|
||||
|
||||
return view('secure/logs', ['logs' => $logs, 'names' => $names, 'current_name' => $name, 'cols' => $cols]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs page submitted
|
||||
*/
|
||||
public function logsSubmit(Request $request)
|
||||
{
|
||||
// No need to check permissions here, as they are checked in routing
|
||||
|
||||
$name = '';
|
||||
if (!empty($request->name)) {
|
||||
$activities = ActivityLog::inLog($request->name)->orderBy('created_at', 'desc')->get();
|
||||
$name = $request->name;
|
||||
} elseif (count($names = ActivityLog::select('log_name')->distinct()->get()->pluck('log_name'))) {
|
||||
$activities = ActivityLog::inLog($names[0])->orderBy('created_at', 'desc')->get();
|
||||
$name = $names[0];
|
||||
}
|
||||
|
||||
switch ($request->action) {
|
||||
case 'clean':
|
||||
if ($name) {
|
||||
ActivityLog::where('log_name', $name)->delete();
|
||||
\Session::flash('flash_success_floating', __('Log successfully cleaned'));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return redirect()->route('logs', ['name' => $name]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
131
app/Jobs/SendAutoReply.php
Normal file
131
app/Jobs/SendAutoReply.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Mail\AutoReply;
|
||||
use App\SendLog;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Mail;
|
||||
|
||||
class SendAutoReply implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $conversation;
|
||||
|
||||
public $thread;
|
||||
|
||||
public $mailbox;
|
||||
|
||||
public $customer;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($conversation, $thread, $mailbox, $customer)
|
||||
{
|
||||
$this->conversation = $conversation;
|
||||
$this->thread = $thread;
|
||||
$this->mailbox = $mailbox;
|
||||
$this->customer = $customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Configure mail driver according to Mailbox settings
|
||||
\App\Mail\Mail::setMailDriver($this->mailbox);
|
||||
|
||||
// Auto reply appears as reply in customer's mailbox
|
||||
$headers['In-Reply-To'] = '<'.$this->thread->message_id.'>';
|
||||
$headers['References'] = '<'.$this->thread->message_id.'>';
|
||||
|
||||
// Create Message-ID for the auto reply
|
||||
$message_id = \App\Mail\Mail::MESSAGE_ID_PREFIX_AUTO_REPLY.'-'.$this->thread->id.'-'.md5($this->thread->id).'@'.$this->mailbox->getEmailDomain();
|
||||
$headers['Message-ID'] = $message_id;
|
||||
|
||||
$customer_email = $this->customer->getMainEmail(); // todo: get customer email linked to conversation
|
||||
$recipients = [$customer_email];
|
||||
$failures = [];
|
||||
$exception = null;
|
||||
|
||||
try {
|
||||
Mail::to([['name' => $this->customer->getFullName(), 'email' => $customer_email]])
|
||||
->send(new AutoReply($this->conversation, $this->mailbox, $this->customer, $headers));
|
||||
} catch (\Exception $e) {
|
||||
// We come here in case SMTP server unavailable for example
|
||||
activity()
|
||||
->causedBy($this->customer)
|
||||
->withProperties([
|
||||
'error' => $e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')',
|
||||
])
|
||||
->useLog(\App\ActivityLog::NAME_EMAILS_SENDING)
|
||||
->log(\App\ActivityLog::DESCRIPTION_EMAILS_SENDING_ERROR_TO_CUSTOMER);
|
||||
|
||||
// Failures will be saved to send log when retry attempts will finish
|
||||
$failures = $recipients;
|
||||
|
||||
$exception = $e;
|
||||
}
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
$status_message = '';
|
||||
if ($exception) {
|
||||
$status = SendLog::STATUS_SEND_ERROR;
|
||||
$status_message = $exception->getMessage();
|
||||
} else {
|
||||
$failures = Mail::failures();
|
||||
|
||||
// Status for send log
|
||||
if (!empty($failures) && in_array($recipient, $failures)) {
|
||||
$status = SendLog::STATUS_SEND_ERROR;
|
||||
} else {
|
||||
$status = SendLog::STATUS_ACCEPTED;
|
||||
}
|
||||
}
|
||||
if ($customer_email == $recipient) {
|
||||
$customer_id = $this->customer->id;
|
||||
} else {
|
||||
$customer_id = null;
|
||||
}
|
||||
|
||||
SendLog::log($this->thread->id, $message_id, $recipient, SendLog::MAIL_TYPE_AUTO_REPLY, $status, $customer_id, null, $status_message);
|
||||
}
|
||||
|
||||
if ($exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The job failed to process.
|
||||
* This method is called after attempts had finished.
|
||||
* At this stage method has access only to variables passed in constructor.
|
||||
*
|
||||
* @param Exception $exception
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function failed(\Exception $e)
|
||||
{
|
||||
// Write to activity log
|
||||
activity()
|
||||
->causedBy($this->customer)
|
||||
->withProperties([
|
||||
'error' => $e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')',
|
||||
//'to' => $this->customer->getMainEmail(),
|
||||
])
|
||||
->useLog(\App\ActivityLog::NAME_EMAILS_SENDING)
|
||||
->log(\App\ActivityLog::DESCRIPTION_EMAILS_SENDING_ERROR_TO_CUSTOMER);
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,7 @@ class SendNotificationToUsers implements ShouldQueue
|
||||
$global_exception = $e;
|
||||
}
|
||||
|
||||
$status_message = '';
|
||||
if ($exception) {
|
||||
$status = SendLog::STATUS_SEND_ERROR;
|
||||
$status_message = $exception->getMessage();
|
||||
@@ -112,7 +113,7 @@ class SendNotificationToUsers implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
SendLog::log($last_thread->id, $message_id, $user->email, $status, null, $user->id, $status_message);
|
||||
SendLog::log($last_thread->id, $message_id, $user->email, SendLog::MAIL_TYPE_USER_NOTIFICATION, $status, null, $user->id, $status_message);
|
||||
}
|
||||
|
||||
if ($global_exception) {
|
||||
@@ -129,16 +130,16 @@ class SendNotificationToUsers implements ShouldQueue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// public function failed(\Exception $e)
|
||||
// {
|
||||
// // Write to activity log
|
||||
// activity()
|
||||
// //->causedBy($this->customer)
|
||||
// ->withProperties([
|
||||
// 'error' => $e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')',
|
||||
// //'to' => $this->customer->getMainEmail(),
|
||||
// ])
|
||||
// ->useLog(\App\ActivityLog::NAME_EMAILS_SENDING)
|
||||
// ->log(\App\ActivityLog::DESCRIPTION_EMAILS_SENDING_ERROR_TO_USER);
|
||||
// }
|
||||
public function failed(\Exception $e)
|
||||
{
|
||||
// Write to activity log
|
||||
activity()
|
||||
//->causedBy($this->customer)
|
||||
->withProperties([
|
||||
'error' => $e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')',
|
||||
//'to' => $this->customer->getMainEmail(),
|
||||
])
|
||||
->useLog(\App\ActivityLog::NAME_EMAILS_SENDING)
|
||||
->log(\App\ActivityLog::DESCRIPTION_EMAILS_SENDING_ERROR_TO_USER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,19 +132,19 @@ class SendReplyToCustomer implements ShouldQueue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
// public function failed(\Exception $e)
|
||||
// {
|
||||
// activity()
|
||||
// ->causedBy($this->customer)
|
||||
// ->withProperties([
|
||||
// 'error' => $e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')',
|
||||
// 'to' => $this->customer->getMainEmail(),
|
||||
// ])
|
||||
// ->useLog(\App\ActivityLog::NAME_EMAILS_SENDING)
|
||||
// ->log(\App\ActivityLog::DESCRIPTION_EMAILS_SENDING_ERROR_TO_CUSTOMER);
|
||||
public function failed(\Exception $e)
|
||||
{
|
||||
activity()
|
||||
->causedBy($this->customer)
|
||||
->withProperties([
|
||||
'error' => $e->getMessage().'; File: '.$e->getFile().' ('.$e->getLine().')',
|
||||
'to' => $this->customer->getMainEmail(),
|
||||
])
|
||||
->useLog(\App\ActivityLog::NAME_EMAILS_SENDING)
|
||||
->log(\App\ActivityLog::DESCRIPTION_EMAILS_SENDING_ERROR_TO_CUSTOMER);
|
||||
|
||||
// $this->saveToSendLog();
|
||||
// }
|
||||
$this->saveToSendLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save emails to send log.
|
||||
@@ -164,7 +164,7 @@ class SendReplyToCustomer implements ShouldQueue
|
||||
} else {
|
||||
$customer_id = null;
|
||||
}
|
||||
SendLog::log($this->last_thread->id, $this->message_id, $recipient, $status, $customer_id, null, $status_message);
|
||||
SendLog::log($this->last_thread->id, $this->message_id, $recipient, SendLog::MAIL_TYPE_EMAIL_TO_CUSTOMER, $status, $customer_id, null, $status_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
app/Listeners/SendAutoReply.php
Normal file
43
app/Listeners/SendAutoReply.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\SendLog;
|
||||
|
||||
class SendAutoReply
|
||||
{
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
$conversation = $event->conversation;
|
||||
|
||||
if (!$conversation->imported && $conversation->mailbox->auto_reply_enabled) {
|
||||
|
||||
// Send auto reply once in 24h
|
||||
$created_at = \Illuminate\Support\Carbon::now()->subDays(1);
|
||||
$auto_reply_sent = SendLog::where('customer_id', $conversation->customer_id)
|
||||
->where('mail_type', SendLog::MAIL_TYPE_AUTO_REPLY)
|
||||
->where('created_at', '>', $created_at)
|
||||
->first();
|
||||
|
||||
if ($auto_reply_sent) {
|
||||
return;
|
||||
}
|
||||
|
||||
\App\Jobs\SendAutoReply::dispatch($conversation, $conversation->threads()->first(), $conversation->mailbox, $conversation->customer)
|
||||
->onQueue('emails');
|
||||
}
|
||||
}
|
||||
}
|
||||
103
app/Mail/AutoReply.php
Normal file
103
app/Mail/AutoReply.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Mail\Mailer as MailerContract;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class AutoReply extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Conversation created by customer.
|
||||
*
|
||||
*/
|
||||
public $conversation;
|
||||
|
||||
/**
|
||||
* Mailbox.
|
||||
*
|
||||
*/
|
||||
public $mailbox;
|
||||
|
||||
/**
|
||||
* Customer.
|
||||
*
|
||||
*/
|
||||
public $customer;
|
||||
|
||||
/**
|
||||
* Custom headers.
|
||||
*
|
||||
*/
|
||||
public $headers = [];
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
*/
|
||||
public function __construct($conversation, $mailbox, $customer, $headers)
|
||||
{
|
||||
$this->conversation = $conversation;
|
||||
$this->mailbox = $mailbox;
|
||||
$this->customer = $customer;
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$view_params = [];
|
||||
|
||||
// Set headers
|
||||
$this->setHeaders();
|
||||
|
||||
$data = [
|
||||
'mailbox' => $this->mailbox,
|
||||
'conversation' => $this->conversation,
|
||||
'customer' => $this->customer,
|
||||
];
|
||||
|
||||
// Set variables
|
||||
$subject = \App\Mail\Mail::replaceMailVars($this->mailbox->auto_reply_subject, $data);
|
||||
$view_params['auto_reply_message'] = \App\Mail\Mail::replaceMailVars($this->mailbox->auto_reply_message, $data);
|
||||
|
||||
$message = $this->subject($subject)
|
||||
->view('emails/customer/auto_reply', $view_params)
|
||||
->text('emails/customer/auto_reply_text', $view_params);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set headers.
|
||||
* Settings via $this->addCustomHeaders does not work.
|
||||
*/
|
||||
public function setHeaders()
|
||||
{
|
||||
$new_headers = $this->headers;
|
||||
if (!empty($new_headers)) {
|
||||
$this->withSwiftMessage(function ($swiftmessage) use ($new_headers) {
|
||||
if (!empty($new_headers['Message-ID'])) {
|
||||
$swiftmessage->setId($new_headers['Message-ID']);
|
||||
}
|
||||
$headers = $swiftmessage->getHeaders();
|
||||
foreach ($new_headers as $header => $value) {
|
||||
if ($header != 'Message-ID') {
|
||||
$headers->addTextHeader($header, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $swiftmessage;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ class Mail
|
||||
const MESSAGE_ID_PREFIX_NOTIFICATION = 'notify';
|
||||
const MESSAGE_ID_PREFIX_NOTIFICATION_IN_REPLY = 'conversation';
|
||||
const MESSAGE_ID_PREFIX_REPLY_TO_CUSTOMER = 'reply';
|
||||
const MESSAGE_ID_PREFIX_AUTO_REPLY = 'autoreply';
|
||||
|
||||
/**
|
||||
* If reply is not extracted properly from the incoming email, add here new separator.
|
||||
@@ -58,4 +59,24 @@ class Mail
|
||||
|
||||
(new \Illuminate\Mail\MailServiceProvider(app()))->register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace mail vars in the text.
|
||||
*/
|
||||
public static function replaceMailVars($text, $data = [])
|
||||
{
|
||||
// Available variables to insert into email in UI.
|
||||
$vars = [
|
||||
'{%subject%}' => $data['conversation']->subject,
|
||||
'{%mailbox.email%}' => $data['mailbox']->email,
|
||||
'{%mailbox.name%}' => $data['mailbox']->name,
|
||||
'{%conversation.number%}' => $data['conversation']->number,
|
||||
'{%customer.fullName%}' => $data['customer']->getFullName(true),
|
||||
'{%customer.firstName%}' => $data['customer']->getFirstName(true),
|
||||
'{%customer.lastName%}' => $data['customer']->last_name,
|
||||
'{%customer.email%}' => $data['customer']->getMainEmail()
|
||||
];
|
||||
|
||||
return strtr($text, $vars);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class ReplyToCustomer extends Mailable
|
||||
public $threads;
|
||||
|
||||
/**
|
||||
* Custome haders.
|
||||
* Custom headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
|
||||
@@ -86,6 +86,19 @@ class Mailbox extends Model
|
||||
const RATINGS_PLACEMENT_ABOVE = 1;
|
||||
const RATINGS_PLACEMENT_BELOW = 2;
|
||||
|
||||
/**
|
||||
* Default signature set when mailbox created.
|
||||
*/
|
||||
const DEFAULT_SIGNATURE = '<span style="color:#808080;">--<br>
|
||||
{%mailbox.name%}<br></span>';
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*/
|
||||
protected $attributes = [
|
||||
'signature' => self::DEFAULT_SIGNATURE,
|
||||
];
|
||||
|
||||
/**
|
||||
* Attributes fillable using fill() method.
|
||||
*
|
||||
|
||||
@@ -61,6 +61,7 @@ class EventServiceProvider extends ServiceProvider
|
||||
],
|
||||
|
||||
'App\Events\CustomerCreatedConversation' => [
|
||||
'App\Listeners\SendAutoReply',
|
||||
'App\Listeners\SendNotificationToUsers',
|
||||
],
|
||||
|
||||
|
||||
@@ -22,6 +22,14 @@ class SendLog extends Model
|
||||
const STATUS_UNSUBSCRIBED = 8;
|
||||
const STATUS_COMPLAINED = 9;
|
||||
|
||||
/**
|
||||
* Mail types.
|
||||
*/
|
||||
const MAIL_TYPE_EMAIL_TO_CUSTOMER = 1;
|
||||
const MAIL_TYPE_USER_NOTIFICATION = 2;
|
||||
const MAIL_TYPE_AUTO_REPLY = 3;
|
||||
const MAIL_TYPE_WRONG_USER_EMAIL_MESSAGE = 4;
|
||||
|
||||
/**
|
||||
* The attributes that are not mass assignable.
|
||||
*
|
||||
@@ -56,12 +64,13 @@ class SendLog extends Model
|
||||
/**
|
||||
* Save log record.
|
||||
*/
|
||||
public static function log($thread_id, $message_id, $email, $status, $customer_id = null, $user_id = null, $status_message = null)
|
||||
public static function log($thread_id, $message_id, $email, $mail_type, $status, $customer_id = null, $user_id = null, $status_message = null)
|
||||
{
|
||||
$send_log = new self();
|
||||
$send_log->thread_id = $thread_id;
|
||||
$send_log->message_id = $message_id;
|
||||
$send_log->email = $email;
|
||||
$send_log->mail_type = $mail_type;
|
||||
$send_log->status = $status;
|
||||
$send_log->customer_id = $customer_id;
|
||||
$send_log->user_id = $user_id;
|
||||
|
||||
@@ -168,7 +168,7 @@ return [
|
||||
| PHP extensions required by the app
|
||||
|-------------------------------------------------------------------------
|
||||
*/
|
||||
'required_extensions' => ['mysql / mysqli', 'mbstring', 'xml', 'imap', 'mcrypt', 'json', 'openssl', 'tokenizer'/*, 'dom', 'xmlwriter', 'tokenizer', 'libxml', 'phar'*/],
|
||||
'required_extensions' => ['mysql / mysqli', 'mbstring', 'xml', 'imap', /*'mcrypt' mcrypt is deprecated*/ 'json', 'openssl', 'tokenizer'/*, 'dom', 'xmlwriter', 'tokenizer', 'libxml', 'phar'*/],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -11,6 +11,6 @@ $factory->define(App\Mailbox::class, function (Faker $faker) {
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'aliases' => 'support@'.$domain.',help@'.$domain.', contact@'.$domain,
|
||||
'signature' => '--<br/>'.$name,
|
||||
//'signature' => '--<br/>'.$name,
|
||||
];
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ class CreateSendLogsTable extends Migration
|
||||
$table->string('message_id', 998);
|
||||
// We have to keep email as customer's or user's email may change
|
||||
$table->string('email', 191);
|
||||
$table->unsignedTinyInteger('mail_type');
|
||||
$table->unsignedTinyInteger('status');
|
||||
$table->string('status_message', 255)->nullable();
|
||||
$table->timestamps();
|
||||
@@ -32,6 +33,8 @@ class CreateSendLogsTable extends Migration
|
||||
// Indexes
|
||||
// https://github.com/laravel/framework/issues/9293#issuecomment-373229281
|
||||
$table->index([DB::raw('message_id(191)')], 'send_logs_message_id_index');
|
||||
// Used when sending auto reply
|
||||
$table->index(['customer_id', 'mail_type', 'created_at']);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
2
public/css/bootstrap.css
vendored
2
public/css/bootstrap.css
vendored
@@ -3020,7 +3020,7 @@ select[multiple].input-lg {
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
height: 30px;
|
||||
/*height: 30px;*/
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
12
public/css/style.css
vendored
12
public/css/style.css
vendored
@@ -605,7 +605,7 @@ a h4 {
|
||||
display: none;
|
||||
padding: 8px 20px;
|
||||
}
|
||||
.dash-card-inactive-content .help-block {
|
||||
.dash-card-inactive-content .block-help {
|
||||
font-size: 14px;
|
||||
}
|
||||
.dash-card-inactive-content .btn-link {
|
||||
@@ -1698,7 +1698,7 @@ table.table-conversations td.conv-attachment {
|
||||
.customer-social-profiles {
|
||||
position: static;
|
||||
}
|
||||
.panel-heading {
|
||||
.conv-customer-hist .panel-heading {
|
||||
display: none;
|
||||
}
|
||||
.customer-hist-trigger {
|
||||
@@ -1856,7 +1856,7 @@ table.table-conversations td.conv-attachment {
|
||||
height: 31px;
|
||||
margin-top: -15px;
|
||||
}
|
||||
.modal-body p.help-block {
|
||||
.modal-body p.block-help {
|
||||
font-size: 11.4px;
|
||||
}
|
||||
.modal-body.modal-body-fit {
|
||||
@@ -2058,16 +2058,16 @@ a.help-icon:hover {
|
||||
color:#4f5d6b;
|
||||
font-size:13.4px
|
||||
}
|
||||
.help-block {
|
||||
.block-help {
|
||||
color: #93a1af;
|
||||
display: block;
|
||||
font-size: 13.4px;
|
||||
margin: 4px 0 9px;
|
||||
}
|
||||
.help-block a {
|
||||
.block-help a {
|
||||
color: #93a1af;
|
||||
}
|
||||
.help-block a:hover {
|
||||
.block-help a:hover {
|
||||
color: #23527c;
|
||||
}
|
||||
.text-help {
|
||||
|
||||
2
public/js/main.js
vendored
2
public/js/main.js
vendored
@@ -176,7 +176,7 @@ function summernoteInit(selector)
|
||||
followingToolbar: false,
|
||||
toolbar: [
|
||||
// [groupName, [list of button]]
|
||||
['style', ['bold', 'italic', 'underline', 'ul', 'ol', 'link', 'codeview']],
|
||||
['style', ['bold', 'italic', 'underline', 'color', 'ul', 'ol', 'link', 'codeview']],
|
||||
]
|
||||
});
|
||||
$('.note-statusbar').remove();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>{{ __("Customer") }}</th>
|
||||
<th>{{ __("Remarks") }}</th>
|
||||
<th>{{ __("Date") }}</th>
|
||||
<th>{{ __("Status") }}</th>
|
||||
</tr>
|
||||
@@ -16,6 +17,7 @@
|
||||
@if ($loop->index == 0)
|
||||
<td rowspan="{{ count($logs) }}">{{ $email }}</td>
|
||||
@endif
|
||||
<td>@if ($log->mail_type == App\SendLog::MAIL_TYPE_AUTO_REPLY) [{{ __('auto reply') }}] @else @endif</td>
|
||||
<td>{{ App\User::dateFormat($log->created_at, 'M j, Y H:i:s') }}</td>
|
||||
<td>
|
||||
<span class="@if ($log->isErrorStatus())text-danger @elseif ($log->isSuccessStatus()) text-success @endif">{{ $log->getStatusName() }}</span>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<input type="hidden" name="after_send" id="after_send" value="{{ $after_send }}"/>
|
||||
<input type="hidden" name="after_send" id="after_send" value="{{ $after_send }}" data-parsley-exclude="true"/>
|
||||
<div class="btn-group btn-group-send">
|
||||
<button class="hidden"></button>
|
||||
<button type="button" class="btn btn-primary btn-reply-submit btn-send-text" data-loading-text="{{ __('Sending…') }}">{{ __('Send') }}</button>
|
||||
@@ -49,7 +49,7 @@
|
||||
<option value="{{ App\MailboxUser::AFTER_SEND_FOLDER }}" @if ($after_send == App\MailboxUser::AFTER_SEND_FOLDER)selected="selected"@endif>{{ __('Back to folder') }}</option>
|
||||
</select>
|
||||
|
||||
<p class="help-block">
|
||||
<p class="block-help">
|
||||
{{ __('This setting gives you control over what page loads after you perform an action (send a reply, add a note, etc.).') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -115,11 +115,10 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('body') ? ' has-error' : '' }} conv-reply-body">
|
||||
|
||||
<textarea id="body" class="form-control" name="body" rows="13" data-parsley-required="true" data-parsley-required-message="{{ __('Please enter a message') }}">{{ old('body', $conversation->body) }}</textarea>
|
||||
<div class="help-block has-error">
|
||||
@include('partials/field_error', ['field'=>'body'])
|
||||
</div>
|
||||
<textarea id="body" class="form-control" name="body" rows="13" data-parsley-required="true" data-parsley-required-message="{{ __('Please enter a message') }}">{{ old('body', $conversation->body) }}</textarea>
|
||||
<div class="help-block has-error">
|
||||
@include('partials/field_error', ['field'=>'body'])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<a href="javascript:void(0)" class="multi-remove" tabindex="-1"><i class="glyphicon glyphicon-remove"></i></a>
|
||||
</div>
|
||||
@endforeach
|
||||
<p class="help-block"><a href="javascript:void(0)" class="multi-add " tabindex="-1">{{ __('Add an email address') }}</a></p>
|
||||
<p class="block-help"><a href="javascript:void(0)" class="multi-add " tabindex="-1">{{ __('Add an email address') }}</a></p>
|
||||
</div>
|
||||
|
||||
@include('partials/field_error', ['field'=>'emails'])
|
||||
@@ -75,7 +75,7 @@
|
||||
<a href="javascript:void(0)" class="multi-remove" tabindex="-1"><i class="glyphicon glyphicon-remove"></i></a>
|
||||
</div>
|
||||
@endforeach
|
||||
<p class="help-block"><a href="javascript:void(0)" class="multi-add" tabindex="-1">{{ __('Add a website') }}</a></p>
|
||||
<p class="block-help"><a href="javascript:void(0)" class="multi-add" tabindex="-1">{{ __('Add a website') }}</a></p>
|
||||
</div>
|
||||
|
||||
@include('partials/field_error', ['field'=>'websites'])
|
||||
|
||||
13
resources/views/emails/customer/auto_reply.blade.php
Normal file
13
resources/views/emails/customer/auto_reply.blade.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
</head>
|
||||
<body bgcolor="#ffffff">
|
||||
<div id="{{ App\Mail\Mail::REPLY_SEPARATOR_HTML }}" class="{{ App\Mail\Mail::REPLY_SEPARATOR_HTML }}">
|
||||
<div style="font-family:sans-serif;">
|
||||
{!! $auto_reply_message !!}
|
||||
</div>
|
||||
</div>
|
||||
{{--<span height="0" style="font-size: 0px; height:0px; line-height: 0px; color:#ffffff;">{#FS:123-123#}</span>--}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
{{ App\Mail\Mail::REPLY_SEPARATOR_TEXT }}
|
||||
|
||||
{{ (new Html2Text\Html2Text($auto_reply_message))->getText() }}
|
||||
@@ -58,7 +58,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@if (Auth::user()->isAdmin())
|
||||
{{--@if (Auth::user()->isAdmin())
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true" v-pre>
|
||||
{{ __('Docs') }} <span class="caret"></span>
|
||||
@@ -82,7 +82,7 @@
|
||||
<li><a href="#">{{ __('Docs') }} (todo)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@endif
|
||||
@endif--}}
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true" v-pre>
|
||||
{{ __('Manage') }} <span class="caret"></span>
|
||||
@@ -90,16 +90,16 @@
|
||||
|
||||
<ul class="dropdown-menu">
|
||||
@if (Auth::user()->isAdmin())
|
||||
<li><a href="#">{{ __('Apps') }} (todo)</a></li>
|
||||
<li><a href="#">{{ __('Plugins') }} (todo)</a></li>
|
||||
{{--<li><a href="#">{{ __('Apps') }} (todo)</a></li>--}}
|
||||
<li><a href="#">{{ __('Company') }} (todo)</a></li>
|
||||
<li><a href="#">{{ __('Docs') }} (todo)</a></li>
|
||||
{{--<li><a href="#">{{ __('Docs') }} (todo)</a></li>--}}
|
||||
<li><a href="{{ route('mailboxes') }}">{{ __('Mailboxes') }}</a></li>
|
||||
@endif
|
||||
<li><a href="#">{{ __('Tags') }} (todo)</a></li>
|
||||
@if (Auth::user()->isAdmin())
|
||||
<li><a href="#">{{ __('Teams') }} (todo)</a></li>
|
||||
{{--<li><a href="#">{{ __('Teams') }} (todo)</a></li>--}}
|
||||
<li><a href="{{ route('users') }}">{{ __('Users') }}</a></li>
|
||||
<li><a href="#">{{ __('Plugins') }} (todo)</a></li>
|
||||
<li><a href="{{ route('logs') }}">{{ __('Logs') }}</a></li>
|
||||
<li><a href="{{ route('system') }}">{{ __('System') }}</a></li>
|
||||
@endif
|
||||
@@ -184,6 +184,8 @@
|
||||
|
||||
<div id="loader-main"></div>
|
||||
|
||||
@include('partials/floating_flash_messages')
|
||||
|
||||
@yield('body_bottom')
|
||||
|
||||
<!-- Scripts -->
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
<div class="col-md-9 auto_reply_message-editor">
|
||||
<textarea id="auto_reply_message" class="form-control" name="auto_reply_message" rows="8">{{ old('auto_reply_message', $mailbox->auto_reply_message) }}</textarea>
|
||||
<p class="help-block">
|
||||
<p class="block-help">
|
||||
{{ __("Auto replies don't include your mailbox signature, so be sure to add your contact information if necessary.") }}
|
||||
</p>
|
||||
@include('partials/field_error', ['field'=>'auto_reply_message'])
|
||||
|
||||
@@ -30,10 +30,6 @@
|
||||
<input id="email" type="email" class="form-control input-sized" name="email" value="{{ $mailbox->email }}" disabled="disabled">
|
||||
<a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}#email" class="btn btn-link btn-sm" data-toggle="tooltip" title="{{ __('Change address in mailbox settings') }}">{{ __('Change') }}</a>
|
||||
</div>
|
||||
|
||||
{{--<div class="col-sm-offset-2 col-md-6">
|
||||
<p class="help-block margin-bottom-0"><strong>{{ __('ATTENTION') }}:</strong> {{ __('All emails from this address will be deleted') }}</p>
|
||||
</div>--}}
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('in_protocol') ? ' has-error' : '' }}">
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</div>
|
||||
|
||||
<div class="col-sm-offset-4 col-md-6">
|
||||
<p class="help-block margin-bottom-0">{{ __('You can edit this later') }}</p>
|
||||
<p class="block-help margin-bottom-0">{{ __('You can edit this later') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h3> {{ __('Selected Users have access to this mailbox:') }}</h3>
|
||||
<p class="help-block">{{ __('Administrators have access to all mailboxes and are not listed here.') }}</p>
|
||||
<p class="block-help">{{ __('Administrators have access to all mailboxes and are not listed here.') }}</p>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<form method="POST" action="">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.update')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-pencil"></i> {{ __('Edit Mailbox') }}</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.connection' || Route::currentRouteName() == 'mailboxes.connection.incoming')class="active"@endif><a href="{{ route('mailboxes.connection', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-transfer"></i> {{ __('Connection Settings') }}</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.permissions')class="active"@endif><a href="{{ route('mailboxes.permissions', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-ok"></i> {{ __('Permissions') }}</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.fields')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-list"></i> {{ __('Custom Fields') }} (todo)</a></li>
|
||||
{{--<li @if (Route::currentRouteName() == 'mailboxes.fields')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-list"></i> {{ __('Custom Fields') }} (todo)</a></li>--}}
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.auto_reply')class="active"@endif><a href="{{ route('mailboxes.auto_reply', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-share"></i> {{ __('Auto Reply') }}</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.savedreplies')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-comment"></i> {{ __('Saved Replies') }} (todo)</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.workflows')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-random"></i> {{ __('Workflows') }} (todo)</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.ratings')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-thumbs-up"></i> {{ __('Sat. Ratings') }} (todo)</a></li>
|
||||
{{--<li @if (Route::currentRouteName() == 'mailboxes.workflows')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-random"></i> {{ __('Workflows') }} (todo)</a></li>
|
||||
<li @if (Route::currentRouteName() == 'mailboxes.ratings')class="active"@endif><a href="{{ route('mailboxes.update', ['id'=>$mailbox->id]) }}"><i class="glyphicon glyphicon-thumbs-up"></i> {{ __('Sat. Ratings') }} (todo)</a></li>--}}
|
||||
@@ -16,29 +16,9 @@
|
||||
{{ session('flash_error') }}
|
||||
</div>
|
||||
@endif
|
||||
@if (session('flash_success_floating'))
|
||||
@section('body_bottom')
|
||||
<div class="alert alert-success alert-floating">
|
||||
<i class="glyphicon glyphicon-ok"></i>
|
||||
<div>{!! session('flash_success_floating') !!}</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endif
|
||||
@if (session('flash_error_floating'))
|
||||
@section('body_bottom')
|
||||
<div class="alert alert-danger alert-floating">
|
||||
<i class="glyphicon glyphicon-exclamation-sign"></i>
|
||||
<div>{!! session('flash_error_floating') !!}</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endif
|
||||
@if (session('flash_warning_floating'))
|
||||
@section('body_bottom')
|
||||
<div class="alert alert-warning alert-floating">
|
||||
<div>{!! session('flash_warning_floating') !!}</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endif
|
||||
|
||||
{{-- Floating flash messages are displayed in layout --}}
|
||||
|
||||
@if (!empty($flashes) && is_array($flashes))
|
||||
@foreach ($flashes as $flash)
|
||||
<div class="alert alert-{{ $flash['type'] }}">
|
||||
|
||||
23
resources/views/partials/floating_flash_messages.blade.php
Normal file
23
resources/views/partials/floating_flash_messages.blade.php
Normal file
@@ -0,0 +1,23 @@
|
||||
@if (session('flash_success_floating'))
|
||||
@section('body_bottom')
|
||||
<div class="alert alert-success alert-floating">
|
||||
<i class="glyphicon glyphicon-ok"></i>
|
||||
<div>{!! session('flash_success_floating') !!}</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endif
|
||||
@if (session('flash_error_floating'))
|
||||
@section('body_bottom')
|
||||
<div class="alert alert-danger alert-floating">
|
||||
<i class="glyphicon glyphicon-exclamation-sign"></i>
|
||||
<div>{!! session('flash_error_floating') !!}</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endif
|
||||
@if (session('flash_warning_floating'))
|
||||
@section('body_bottom')
|
||||
<div class="alert alert-warning alert-floating">
|
||||
<div>{!! session('flash_warning_floating') !!}</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endif
|
||||
@@ -20,7 +20,7 @@
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="dash-card-inactive-content">
|
||||
<div class="help-block">
|
||||
<div class="block-help">
|
||||
{{ __('Administrator has not configured mailbox connection settings yet.') }}
|
||||
</div>
|
||||
@if (Auth::user()->can('update', $mailbox))
|
||||
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="section-heading margin-bottom">
|
||||
{{ __('Log Records') }}
|
||||
</div>
|
||||
<form method="post">
|
||||
{{ csrf_field() }}
|
||||
<div class="section-heading margin-bottom">
|
||||
{{ __('Log Records') }} <button type="submit" name="action" value="clean" class="btn btn-default btn-xs" data-toggle="tooltip" title="{{ __('Clean this log') }}">{{ __('Clean Log') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (count($logs))
|
||||
<table id="table-logs" class="stripe hover order-column row-border" style="width:100%">
|
||||
<thead>
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
<div class="col-md-6">
|
||||
<input type="file" name="photo" id="photo" disabled="disabled">
|
||||
<p class="help-block">{{ __('Image will be re-sized to 200x200. JPG, GIF, PNG accepted.') }}</p>
|
||||
<p class="block-help">{{ __('Image will be re-sized to 200x200. JPG, GIF, PNG accepted.') }}</p>
|
||||
@include('partials/field_error', ['field'=>'photo_url'])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,6 +23,7 @@ Route::redirect('/home', '/', 301);
|
||||
// General routes for logged in users
|
||||
Route::get('/', 'SecureController@dashboard')->name('dashboard');
|
||||
Route::get('/logs/{name?}', ['uses' => 'SecureController@logs', 'middleware' => ['auth', 'roles'], 'roles' => ['admin']])->name('logs');
|
||||
Route::post('/logs/{name?}', ['uses' => 'SecureController@logsSubmit', 'middleware' => ['auth', 'roles'], 'roles' => ['admin']]);
|
||||
Route::get('/system', ['uses' => 'SecureController@system', 'middleware' => ['auth', 'roles'], 'roles' => ['admin']])->name('system');
|
||||
|
||||
// Users
|
||||
@@ -61,6 +62,7 @@ Route::post('/settings/connection-settings/{id}/outgoing', 'MailboxesController@
|
||||
Route::get('/settings/connection-settings/{id}/incoming', 'MailboxesController@connectionIncoming')->name('mailboxes.connection.incoming');
|
||||
Route::post('/settings/connection-settings/{id}/incoming', 'MailboxesController@connectionIncomingSave');
|
||||
Route::get('/settings/mailbox/{id}/auto-reply', 'MailboxesController@autoReply')->name('mailboxes.auto_reply');
|
||||
Route::post('/settings/mailbox/{id}/auto-reply', 'MailboxesController@autoReplySave');
|
||||
|
||||
// Customers
|
||||
Route::get('/customer/{id}/edit', 'CustomersController@update')->name('customers.update');
|
||||
|
||||
Reference in New Issue
Block a user