Skip to content

Commit c0a1c77

Browse files
authored
Merge pull request #21 from kirschbaum-development/feature/model-events
Feature - Send Mail via Model Events
2 parents 7160748 + 572cb71 commit c0a1c77

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1363
-89
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ phpunit.xml
88
.phpunit.result.cache
99
.DS_Store
1010
Thumbs.db
11+
.php_cs.cache

.php_cs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?php
2+
3+
$finder = PhpCsFixer\Finder::create()
4+
->exclude('bootstrap/cache')
5+
->exclude('storage')
6+
->exclude('vendor')
7+
->exclude('bower_components')
8+
->exclude('node_modules')
9+
->in(__DIR__)
10+
->name('*.php')
11+
->notName('*.blade.php')
12+
->ignoreDotFiles(true)
13+
->ignoreVCS(true);
14+
15+
return PhpCsFixer\Config::create()
16+
->setFinder($finder)
17+
->setRules([
18+
'@PSR2' => true,
19+
'phpdoc_no_empty_return' => false,
20+
'phpdoc_var_annotation_correct_order' => true,
21+
'array_syntax' => [
22+
'syntax' => 'short',
23+
],
24+
'no_singleline_whitespace_before_semicolons' => true,
25+
'no_extra_blank_lines' => [
26+
'break', 'case', 'continue', 'curly_brace_block', 'default',
27+
'extra', 'parenthesis_brace_block', 'return',
28+
'square_brace_block', 'switch', 'throw', 'use', 'useTrait', 'use_trait',
29+
],
30+
'cast_spaces' => [
31+
'space' => 'single',
32+
],
33+
'concat_space' => [
34+
'spacing' => 'one',
35+
],
36+
'ordered_imports' => [
37+
'sort_algorithm' => 'length',
38+
],
39+
'single_quote' => true,
40+
'lowercase_cast' => true,
41+
'lowercase_static_reference' => true,
42+
'no_empty_phpdoc' => true,
43+
'no_empty_comment' => true,
44+
'array_indentation' => true,
45+
// TODO: This isn't working, causes fixer to error.
46+
// 'increment_style' => ['style' => 'post'],
47+
'short_scalar_cast' => true,
48+
'class_attributes_separation' => [
49+
'elements' => ['const', 'method', 'property'],
50+
],
51+
'no_mixed_echo_print' => [
52+
'use' => 'echo',
53+
],
54+
'no_unused_imports' => true,
55+
'binary_operator_spaces' => [
56+
'default' => 'single_space',
57+
],
58+
'no_empty_statement' => true,
59+
'unary_operator_spaces' => true, // $number ++ becomes $number++
60+
'hash_to_slash_comment' => true, // # becomes //
61+
'standardize_not_equals' => true, // <> becomes !=
62+
'native_function_casing' => true,
63+
'ternary_operator_spaces' => true,
64+
'ternary_to_null_coalescing' => true,
65+
'declare_equal_normalize' => [
66+
'space' => 'single',
67+
],
68+
'function_typehint_space' => true,
69+
'no_leading_import_slash' => true,
70+
'blank_line_before_statement' => [
71+
'statements' => [
72+
'break', 'case', 'continue',
73+
'declare', 'default', 'die',
74+
'do', 'exit', 'for', 'foreach',
75+
'goto', 'if', 'include',
76+
'include_once', 'require', 'require_once',
77+
'return', 'switch', 'throw', 'try', 'while', 'yield',
78+
],
79+
],
80+
'combine_consecutive_unsets' => true,
81+
'method_chaining_indentation' => true,
82+
'no_whitespace_in_blank_line' => true,
83+
'blank_line_after_opening_tag' => true,
84+
'no_trailing_comma_in_list_call' => true,
85+
'list_syntax' => ['syntax' => 'short'],
86+
// public function getTimezoneAttribute( ? Banana $value) becomes public function getTimezoneAttribute(?Banana $value)
87+
'compact_nullable_typehint' => true,
88+
'explicit_string_variable' => true,
89+
'no_leading_namespace_whitespace' => true,
90+
'trailing_comma_in_multiline_array' => true,
91+
'not_operator_with_successor_space' => true,
92+
'object_operator_without_whitespace' => true,
93+
'single_blank_line_before_namespace' => true,
94+
'no_blank_lines_after_class_opening' => true,
95+
'no_blank_lines_after_phpdoc' => true,
96+
'no_whitespace_before_comma_in_array' => true,
97+
'no_trailing_comma_in_singleline_array' => true,
98+
'multiline_whitespace_before_semicolons' => [
99+
'strategy' => 'no_multi_line',
100+
],
101+
'no_multiline_whitespace_around_double_arrow' => true,
102+
'no_useless_return' => true,
103+
'phpdoc_add_missing_param_annotation' => true,
104+
'phpdoc_order' => true,
105+
'phpdoc_scalar' => true,
106+
'phpdoc_separation' => true,
107+
'phpdoc_single_line_var_spacing' => true,
108+
'single_trait_insert_per_statement' => true,
109+
'ordered_class_elements' => [
110+
'order' => [
111+
'use_trait',
112+
'constant',
113+
'property',
114+
'construct',
115+
'public',
116+
'protected',
117+
'private',
118+
],
119+
'sortAlgorithm' => 'none',
120+
],
121+
'return_type_declaration' => [
122+
'space_before' => 'none',
123+
],
124+
])
125+
->setLineEnding("\n");

CHANGELOG.md

+15-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
All notable changes to `nova-mail` will be documented in this file
44

5-
## 1.0.0 - TBD
5+
## 0.1.0
66

7-
- initial release
7+
- initial release
8+
- action based mail sending with re-usable templates and sent mail tracking
9+
10+
## 1.0.0
11+
12+
- (new): Send pre-defined templates based on Model Events
13+
- updated config
14+
- cleaned up Vue structure
15+
16+
## Planned
17+
18+
- Tests
19+
- Mail scheduling
20+
- Additional tracking to help prevent duplicate mail sending

README.md

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
![banner](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/banner.png)
2-
# An action based mail package for Nova apps
2+
# Nova Mail
33

44
[![Latest Version on Packagist](https://img.shields.io/packagist/v/kirschbaum-development/nova-mail.svg?style=flat-square)](https://packagist.org/packages/kirschbaum-development/nova-mail)
55
[![Total Downloads](https://img.shields.io/packagist/dt/kirschbaum-development/nova-mail.svg?style=flat-square)](https://packagist.org/packages/kirschbaum-development/nova-mail)
66

7-
This package contains a Nova action that provides a mail sending form for any resource to easily send email.
7+
This package contains a Nova action that provides a mail sending form for any resource to easily send email. It also includes automated mail sending based on Eloquent Model events/attribute changes.
88

99
![screenshot of the send mail action modal](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/send-mail-modal-empty.png)
1010

1111
![screenshot of the send mail action modal with template selected](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/send-mail-modal-template-selected.png)
1212

1313
![screenshot of sent email in mailtrap](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/sent-mail.png)
1414

15+
![screenshot of mail template model events](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/mail-template-model-events.png)
16+
1517
## Requirements
1618

1719
This Nova package requires Nova 2.0 or higher.
1820

21+
Using the mail delay feature requires a queue driver other than sync. If you are using the Amazon SQS queue service, the maximum delay time is 15 minutes.
22+
1923
## Installation
2024

2125
You can install this package in a Laravel app that uses [Nova](https://nova.laravel.com) via composer:
@@ -92,6 +96,18 @@ class User extends Resource
9296

9397
Now you can send emails from the action called "Send Mail" on your resource!
9498

99+
You can also delay any outgoing email by setting the delay in minutes property on the template. Like subject and body, you can override the mail delay specified in the template when you send mail.
100+
101+
### Trigger Mail on Model Events
102+
103+
A `MailTemplate` can be configured to respond to Eloquent Model events, or a value change of a specified column. For example, a mail template informing your users of their account status could be sent when the `active` column on your `User` model is updated:
104+
105+
![screenshot of the account status mail template](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/model-event-account-status-change.png)
106+
107+
You can even have separate Model Events for both "on" an "off"!
108+
109+
![screenshot of the account status with value mail template](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/model-event-account-status-change.png)
110+
95111
### Mail Template Usage/Caveats
96112

97113
The `NovaMailTemplate` resource allows you to create re-usable custom templates for sending email. It works by taking your specified template (or over-ridden template content) and building a temporary blade file (the Blade file can be saved permantely via a configuration option). This blade file is then used in the typical Laravel fashion to send the email.
@@ -160,6 +176,7 @@ If you discover any security related issues, please email adam@kirschbaumdevelop
160176
- [Adam Parker](https://github.com/adammparker)
161177
- [Brandon Ferens](https://github.com/brandonferens)
162178
- [Justin Seliga](https://github.com/jrseliga)
179+
- [Belisar Hoxholli](https://github.com/belisarh)
163180

164181
## Sponsorship
165182

config/nova_mail.php

+18-11
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,34 @@
2727

2828
/*
2929
|--------------------------------------------------------------------------
30-
| Keep Compiled File
30+
| Show Resources
3131
|--------------------------------------------------------------------------
3232
|
33-
| This deterimines if the compiled blade file used for sending the mail
34-
| is kept on the file system after the mail has been delivered.
33+
| This deterimines if the provided Nova resources
34+
| are displayed in the Nova navigation menu.
3535
|
3636
*/
3737

38-
'keep_compiled_file' => false,
38+
'show_resources' => [
39+
'nova_sent_mail' => true,
40+
'nova_mail_template' => true,
41+
'nova_mail_event' => true,
42+
],
3943

4044
/*
4145
|--------------------------------------------------------------------------
42-
| Show Resources
46+
| Classes for dynamic event/column listening
4347
|--------------------------------------------------------------------------
4448
|
45-
| This deterimines if the provided Nova resources
46-
| are displayed in the Nova navigation menu.
49+
| Here you can specify which classes can have dynamic
50+
| listeners for sending Nova Mail Templates.
4751
|
52+
| Ex: [User::class]
53+
|
54+
| Note: These classes must use the Mailable trait and
55+
| implement the abstract method getEmailField.
56+
]
4857
*/
49-
'show_resources' => [
50-
'nova_sent_mail' => true,
51-
'nova_mail_template' => true,
52-
],
58+
59+
'eventables' => [],
5360
];
File renamed without changes.

dist/js/field.js

-1
This file was deleted.

dist/js/fields.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/mix-manifest.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"/js/field.js": "/js/field.js",
3-
"/css/field.css": "/css/field.css"
2+
"/js/fields.js": "/js/fields.js",
3+
"/css/fields.css": "/css/fields.css"
44
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class CreateNovaMailEventsTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('nova_mail_events', function (Blueprint $table) {
17+
$table->bigIncrements('id');
18+
$table->unsignedBigInteger('mail_template_id');
19+
$table->string('model');
20+
$table->string('name');
21+
$table->string('column')->nullable();
22+
$table->string('value')->nullable();
23+
$table->unsignedBigInteger('user_id');
24+
$table->timestamps();
25+
});
26+
}
27+
28+
/**
29+
* Reverse the migrations.
30+
*
31+
* @return void
32+
*/
33+
public function down()
34+
{
35+
Schema::dropIfExists('nova_mail_events');
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class AddMailEventIdColumnToSentMailsTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('nova_sent_mails', function (Blueprint $table) {
17+
$table->unsignedBigInteger('mail_event_id')->nullable();
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::table('nova_sent_mails', function (Blueprint $table) {
29+
$table->dropColumn('mail_event_id');
30+
});
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class AlterClolumnSenderIdOnSentMails extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('nova_sent_mails', function (Blueprint $table) {
17+
$table->unsignedBigInteger('sender_id')->nullable()->change();
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::table('nova_sent_mails', function (Blueprint $table) {
29+
$table->unsignedBigInteger('sender_id')->change();
30+
});
31+
}
32+
}

0 commit comments

Comments
 (0)