Add Notification emails

This commit is contained in:
Matthew Shillam 2018-10-22 02:59:15 +01:00
parent 7b81506dc2
commit 8f0383f786
30 changed files with 999 additions and 26 deletions

View File

@ -1,15 +1,19 @@
<?php
namespace App\Http\Controllers\API\v1;
use App\Notifications\BackupError;
use App\Notifications\BackupSuccess;
use App\Notifications\BackupWarning;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Schedule;
use App\Backup;
use App\Client;
use Carbon\Carbon;
class BackupController extends Controller
{
/**
* Display a listing of the resource.
*
@ -21,6 +25,7 @@ class BackupController extends Controller
return $created_at;
}
/**
* Store a newly created resource in storage.
*
@ -29,36 +34,18 @@ class BackupController extends Controller
*/
public function store($client_id, $schedule_name, Request $request)
{
$message = preg_replace('/:\s+/', '=', $request['message']);
$message = preg_replace('/(?<=\d)\s+(?=\d)/', '-', $message);
$message = preg_replace('/\s+\(/', '(', $message);
$message = preg_replace('/\s+/', '&', $message);
parse_str($message, $data);
$data = parse_duplicati_message($request['message']);
$current_time = Carbon::now()->toDateTimeString();
// Sort out timestamps from $message
dd($data);
$begin_time = parse_duplicati_time($data['BeginTime']);
$end_time = parse_duplicati_time($data['EndTime']);
$schedule = Schedule::updateOrCreate(
['client_id' => $client_id, 'name' => $schedule_name],
['last_backup_status' => $data['ParsedResult'], 'last_backup_time' => $current_time]
);
// $schedule = Schedule::firstOrNew(array(
// 'client_id' => $client_id,
// 'name' => $schedule_name,
// ));
// $schedule->last_backup_status = $data['ParsedResult'];
// $schedule->save();
// Sort out timestamps from $message
$begin_time = str_after($data['BeginTime'], '(');
$begin_time = str_before($begin_time, ')');
$begin_time = Carbon::createFromTimestamp($begin_time)->toDateTimeString();
$end_time = str_after($data['EndTime'], '(');
$end_time = str_before($end_time, ')');
$end_time = Carbon::createFromTimestamp($end_time)->toDateTimeString();
// Create Backup DB entry
$backup = Backup::Create(array(
'schedule_id' => $schedule->id,
@ -91,8 +78,19 @@ class BackupController extends Controller
'version' => $data['Version']
));
return $backup;
// notify client by email.
$client = Client::where('id', '=', $client_id)->first();
if($backup->status == "Success"){
$client->notify(new BackupSuccess($backup));
}
elseif($backup->status == "Warning"){
$client->notify(new BackupWarning($backup));
}
elseif($backup->status == "Error"){
$client->notify(new BackupError($backup));
}
}
@ -107,6 +105,7 @@ class BackupController extends Controller
//
}
/**
* Update the specified resource in storage.
*
@ -119,6 +118,7 @@ class BackupController extends Controller
//
}
/**
* Remove the specified resource from storage.
*

View File

@ -0,0 +1,68 @@
<?php
namespace App\Notifications;
use App\Backup;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class BackupComplete extends Notification
{
use Queueable;
// protected Backup;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(Backup $backup)
{
$this->backup = $backup;
}
/**
* 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 backup schedule ( ' . $this->backup->schedule_name . ' ) has completed succesfully!')
->action('Contact us ', url('/'))
->line($this->backup->schedule_name . ' has completed successfully! yay!')
->line('Size of added files: ' . readableBytes($this->backup->size_of_added_files))
->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

@ -0,0 +1,62 @@
<?php
namespace App\Notifications;
use App\Backup;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class BackupError extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(Backup $backup)
{
$this->backup = $backup;
}
/**
* 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)
->subject('ERROR Your backup ( ' . $this->backup->schedule_name . ' ) has an error!')
->greeting('Error!')
->markdown('mail.backup.error', ['backup' => $this->backup]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace App\Notifications;
use App\Backup;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class BackupSuccess extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(Backup $backup)
{
$this->backup = $backup;
}
/**
* 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)
->subject('SUCCESS Your backup ( ' . $this->backup->schedule_name . ' ) completed succesfully')
->greeting('Success!')
->markdown('mail.backup.success', ['backup' => $this->backup]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace App\Notifications;
use App\Backup;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class BackupWarning extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(Backup $backup)
{
$this->backup = $backup;
}
/**
* 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)
->subject('ERROR Your backup ( ' . $this->backup->schedule_name . ' ) has a warning!')
->greeting('Error!')
->markdown('mail.backup.warning', ['backup' => $this->backup]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@ -0,0 +1,33 @@
@component('mail::message')
<h4 class="error">Error!</h4>
@component('mail::panel')
Your backup schedule ( {{$backup->schedule_name}} ) has errors! See details below...
@endcomponent
@component('mail::button', ['url' => 'mailto:enquiries@mydentalbackup.co.uk?subject=' . $backup->schedule_name . '', 'color' => 'red'])
Contact us.
@endcomponent
@component('mail::table')
| Item | Value |
| :------------ | --------:|
| Number of added files | {{$backup->added_files}} |
| Size of added files | {{$backup->size_of_added_files}} |
| Backup started | {{$backup->started_at}} |
| Backup finished | {{$backup->finished_at}} |
| Total backup time | {{$backup->duration}} |
@endcomponent
<div class="dark-box">
<h1 style="text-align:center;font-weight:normal;color:white;">Full variable data log..</h1>
</div>
@component('mail::panel')
{{$backup}}
@endcomponent
Regards,<br>
{{ config('app.name') }} - auto notification bot.
@endcomponent

View File

@ -0,0 +1,33 @@
@component('mail::message')
####Success!
@component('mail::panel')
Your backup schedule ( {{$backup->schedule_name}} ) was completed successfully. See details below...
@endcomponent
@component('mail::button', ['url' => 'mailto:enquiries@mydentalbackup.co.uk?subject=' . $backup->schedule_name . '', 'color' => 'green'])
Contact us.
@endcomponent
@component('mail::table')
| Item | Value |
| :------------ | --------:|
| Number of added files | {{$backup->added_files}} |
| Size of added files | {{$backup->size_of_added_files}} |
| Backup started | {{$backup->started_at}} |
| Backup finished | {{$backup->finished_at}} |
| Total backup time | {{$backup->duration}} |
@endcomponent
<div class="dark-box">
<h1 style="text-align:center;font-weight:normal;color:white;">Full variable data log..</h1>
</div>
@component('mail::panel')
{{$backup}}
@endcomponent
Regards,<br>
{{ config('app.name') }} - auto notification bot.
@endcomponent

View File

@ -0,0 +1,33 @@
@component('mail::message')
<h4 class="warning">Warning!</h4>
@component('mail::panel')
Your backup schedule ( {{$backup->schedule_name}} ) has warnings! See details below...
@endcomponent
@component('mail::button', ['url' => 'mailto:enquiries@mydentalbackup.co.uk?subject=' . $backup->schedule_name . '', 'color' => 'orange'])
Contact us.
@endcomponent
@component('mail::table')
| Item | Value |
| :------------ | --------:|
| Number of added files | {{$backup->added_files}} |
| Size of added files | {{$backup->size_of_added_files}} |
| Backup started | {{$backup->started_at}} |
| Backup finished | {{$backup->finished_at}} |
| Total backup time | {{$backup->duration}} |
@endcomponent
<div class="dark-box">
<h1 style="text-align:center;font-weight:normal;color:white;">Full variable data log..</h1>
</div>
@component('mail::panel')
{{$backup}}
@endcomponent
Regards,<br>
{{ config('app.name') }} - auto notification bot.
@endcomponent

View File

@ -0,0 +1,19 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@ -0,0 +1,11 @@
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td class="content-cell" align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>

View File

@ -0,0 +1,17 @@
<tr>
<td class="header">
<table class="inner-header" align="center" width="500" cellpadding="0" cellspacing="0">
<tr>
<td>
{{-- <img src="{{url('/svg/logo.svg')}}" style="height: 100px;"/> --}}
<a href="{{ $url }}">
<img src="https://panel.mydentalbackup.co.uk/images/logo-text.png" style="height: 50px;"/>
</a>
{{-- <a href="{{ $url }}">
{{ $slot }}
</a> --}}
</td>
</tr>
</table>
</td>
</tr>

View File

@ -0,0 +1,62 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<style>
@media only screen and (max-width: 600px) {
.inner-body {
width: 100% !important;
}
.inner-header {
width: 100% !important;
}
img {
float: center !important;
}
.footer {
width: 100% !important;
}
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table class="content" width="100%" cellpadding="0" cellspacing="0">
{{ $header ?? '' }}
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0">
<!-- Body content -->
<tr>
<td class="content-cell">
{{ Illuminate\Mail\Markdown::parse($slot) }}
{{ $subcopy ?? '' }}
</td>
</tr>
</table>
</td>
</tr>
{{ $footer ?? '' }}
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent

View File

@ -0,0 +1,13 @@
<table class="panel" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="panel-content">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="panel-item">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@ -0,0 +1,7 @@
<table class="promotion" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>

View File

@ -0,0 +1,13 @@
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<a href="{{ $url }}" class="button button-green" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@ -0,0 +1,7 @@
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td>
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>

View File

@ -0,0 +1,3 @@
<div class="table">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</div>

View File

@ -0,0 +1,334 @@
/* Base */
body, body *:not(html):not(style):not(br):not(tr):not(code) {
font-family: Avenir, Helvetica, sans-serif;
box-sizing: border-box;
}
body {
background-color: #f5f8fa;
color: #74787E;
height: 100%;
hyphens: auto;
line-height: 1.4;
margin: 0;
-moz-hyphens: auto;
-ms-word-break: break-all;
width: 100% !important;
-webkit-hyphens: auto;
-webkit-text-size-adjust: none;
word-break: break-all;
word-break: break-word;
}
p,
ul,
ol,
blockquote {
line-height: 1.4;
text-align: left;
}
a {
color: #3869D4;
}
a img {
border: none;
}
img {
float:left;
}
/* Typography */
h1 {
color: #2F3133;
font-size: 19px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h2 {
color: #2F3133;
font-size: 16px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h3 {
color: #2F3133;
font-size: 14px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h4 {
color: #8BC34A;
font-size: 70px;
font-weight: normal;
margin-top: 0;
margin-bottom: 30px;
text-align: center;
}
p {
color: #74787E;
font-size: 16px;
line-height: 1.5em;
margin-top: 0;
text-align: left;
}
p.sub {
font-size: 12px;
}
img {
max-width: 100%;
}
/* Layout */
.wrapper {
background-color: #f5f8fa;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.content {
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
/* Header */
.header {
padding: 25px 0;
text-align: center;
background-color: white;
}
.header a {
color: #bbbfc3;
font-size: 19px;
font-weight: bold;
text-decoration: none;
text-shadow: 0 1px 0 white;
}
/* Body */
.body {
background-color: #FFFFFF;
border-bottom: 1px solid #EDEFF2;
border-top: 1px solid #EDEFF2;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.inner-body {
background-color: #FFFFFF;
margin: 0 auto;
padding: 0;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
.inner-header {
margin: 0 auto;
padding: 0;
width: 500px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
/* Subcopy */
.subcopy {
border-top: 1px solid #EDEFF2;
margin-top: 25px;
padding-top: 25px;
}
.subcopy p {
font-size: 12px;
}
/* Footer */
.footer {
margin: 0 auto;
padding: 0;
text-align: center;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
.footer p {
color: #AEAEAE;
font-size: 12px;
text-align: center;
}
/* Tables */
.table table {
margin: 30px auto;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.table th {
border-bottom: 1px solid #EDEFF2;
padding-bottom: 8px;
margin: 0;
}
.table td {
color: #74787E;
font-size: 15px;
line-height: 18px;
padding: 10px 0;
margin: 0;
}
.content-cell {
padding: 35px;
}
/* Buttons */
.action {
margin: 30px auto;
padding: 0;
text-align: center;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.button {
border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
color: #FFF;
display: inline-block;
text-decoration: none;
-webkit-text-size-adjust: none;
}
.button-blue,
.button-primary {
background-color: #3097D1;
border-top: 10px solid #3097D1;
border-right: 18px solid #3097D1;
border-bottom: 10px solid #3097D1;
border-left: 18px solid #3097D1;
}
.button-green,
.button-success {
background-color: #8BC34A;
border-top: 10px solid #8BC34A;
border-right: 18px solid #8BC34A;
border-bottom: 10px solid #8BC34A;
border-left: 18px solid #8BC34A;
}
.button-red,
.button-error {
background-color: #ea5b50;
border-top: 10px solid #ea5b50;
border-right: 18px solid #ea5b50;
border-bottom: 10px solid #ea5b50;
border-left: 18px solid #ea5b50;
}
.button-orange,
.button-warning {
background-color: #f1a332;
border-top: 10px solid #f1a332;
border-right: 18px solid #f1a332;
border-bottom: 10px solid #f1a332;
border-left: 18px solid #f1a332;
}
/* Panels */
.panel {
margin: 0 0 21px;
}
.panel-content {
background-color: #EDEFF2;
padding: 16px;
}
.panel-item {
padding: 0;
}
.panel-item p:last-of-type {
margin-bottom: 0;
padding-bottom: 0;
}
/* Promotions */
.promotion {
background-color: #FFFFFF;
border: 1px dashed #9BA2AB;
margin: 0;
margin-bottom: 25px;
margin-top: 25px;
padding: 24px;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.promotion h1 {
text-align: center;
}
.promotion p {
font-size: 15px;
text-align: center;
}
div.dark-box{
background-color:#4e5156; padding:20px; margin-bottom:0px;
}
.error{
color:#ea5b50;
}
.warning{
color:#f1a332;
}

View File

@ -0,0 +1 @@
{{ $slot }}: {{ $url }}

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1 @@
[{{ $slot }}]({{ $url }})

View File

@ -0,0 +1,9 @@
{!! strip_tags($header) !!}
{!! strip_tags($slot) !!}
@isset($subcopy)
{!! strip_tags($subcopy) !!}
@endisset
{!! strip_tags($footer) !!}

View File

@ -0,0 +1,27 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{{ $slot }}
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
@endcomponent
@endslot
@endcomponent

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1 @@
[{{ $slot }}]({{ $url }})

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1 @@
{{ $slot }}

View File

@ -0,0 +1,63 @@
@component('mail::message')
{{-- Greeting --}}
@if (! empty($greeting))
# {{ $greeting }}
@else
@if ($level == 'error')
# @lang('Whoops!')
@else
# @lang('Hello!')
@endif
@endif
{{-- Intro Lines --}}
@foreach ($introLines as $line)
{{ $line }}
@endforeach
{{-- Action Button --}}
@isset($actionText)
<?php
switch ($level) {
case 'success':
case 'error':
$color = $level;
break;
default:
$color = 'primary';
}
?>
@component('mail::button', ['url' => $actionUrl, 'color' => $color])
{{ $actionText }}
@endcomponent
@endisset
{{-- Outro Lines --}}
@foreach ($outroLines as $line)
{{ $line }}
@endforeach
{{-- Salutation --}}
@if (! empty($salutation))
{{ $salutation }}
@else
@lang('Regards'),<br>{{ config('app.name') }}
@endif
{{-- Subcopy --}}
@isset($actionText)
@component('mail::subcopy')
@lang(
"If youre having trouble clicking the \":actionText\" button, copy and paste the URL below\n".
'into your web browser: [:actionURL](:actionURL)',
[
'actionText' => $actionText,
'actionUrl' => $actionUrl
]
)
@endcomponent
@endisset
@endcomponent