Skip to content

Commit

Permalink
Merge pull request #21 from kirschbaum-development/feature/model-events
Browse files Browse the repository at this point in the history
Feature - Send Mail via Model Events
  • Loading branch information
belisarh authored Sep 30, 2020
2 parents 7160748 + 572cb71 commit c0a1c77
Show file tree
Hide file tree
Showing 43 changed files with 1,363 additions and 89 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ phpunit.xml
.phpunit.result.cache
.DS_Store
Thumbs.db
.php_cs.cache
125 changes: 125 additions & 0 deletions .php_cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

$finder = PhpCsFixer\Finder::create()
->exclude('bootstrap/cache')
->exclude('storage')
->exclude('vendor')
->exclude('bower_components')
->exclude('node_modules')
->in(__DIR__)
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);

return PhpCsFixer\Config::create()
->setFinder($finder)
->setRules([
'@PSR2' => true,
'phpdoc_no_empty_return' => false,
'phpdoc_var_annotation_correct_order' => true,
'array_syntax' => [
'syntax' => 'short',
],
'no_singleline_whitespace_before_semicolons' => true,
'no_extra_blank_lines' => [
'break', 'case', 'continue', 'curly_brace_block', 'default',
'extra', 'parenthesis_brace_block', 'return',
'square_brace_block', 'switch', 'throw', 'use', 'useTrait', 'use_trait',
],
'cast_spaces' => [
'space' => 'single',
],
'concat_space' => [
'spacing' => 'one',
],
'ordered_imports' => [
'sort_algorithm' => 'length',
],
'single_quote' => true,
'lowercase_cast' => true,
'lowercase_static_reference' => true,
'no_empty_phpdoc' => true,
'no_empty_comment' => true,
'array_indentation' => true,
// TODO: This isn't working, causes fixer to error.
// 'increment_style' => ['style' => 'post'],
'short_scalar_cast' => true,
'class_attributes_separation' => [
'elements' => ['const', 'method', 'property'],
],
'no_mixed_echo_print' => [
'use' => 'echo',
],
'no_unused_imports' => true,
'binary_operator_spaces' => [
'default' => 'single_space',
],
'no_empty_statement' => true,
'unary_operator_spaces' => true, // $number ++ becomes $number++
'hash_to_slash_comment' => true, // # becomes //
'standardize_not_equals' => true, // <> becomes !=
'native_function_casing' => true,
'ternary_operator_spaces' => true,
'ternary_to_null_coalescing' => true,
'declare_equal_normalize' => [
'space' => 'single',
],
'function_typehint_space' => true,
'no_leading_import_slash' => true,
'blank_line_before_statement' => [
'statements' => [
'break', 'case', 'continue',
'declare', 'default', 'die',
'do', 'exit', 'for', 'foreach',
'goto', 'if', 'include',
'include_once', 'require', 'require_once',
'return', 'switch', 'throw', 'try', 'while', 'yield',
],
],
'combine_consecutive_unsets' => true,
'method_chaining_indentation' => true,
'no_whitespace_in_blank_line' => true,
'blank_line_after_opening_tag' => true,
'no_trailing_comma_in_list_call' => true,
'list_syntax' => ['syntax' => 'short'],
// public function getTimezoneAttribute( ? Banana $value) becomes public function getTimezoneAttribute(?Banana $value)
'compact_nullable_typehint' => true,
'explicit_string_variable' => true,
'no_leading_namespace_whitespace' => true,
'trailing_comma_in_multiline_array' => true,
'not_operator_with_successor_space' => true,
'object_operator_without_whitespace' => true,
'single_blank_line_before_namespace' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_whitespace_before_comma_in_array' => true,
'no_trailing_comma_in_singleline_array' => true,
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'no_multiline_whitespace_around_double_arrow' => true,
'no_useless_return' => true,
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_order' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_single_line_var_spacing' => true,
'single_trait_insert_per_statement' => true,
'ordered_class_elements' => [
'order' => [
'use_trait',
'constant',
'property',
'construct',
'public',
'protected',
'private',
],
'sortAlgorithm' => 'none',
],
'return_type_declaration' => [
'space_before' => 'none',
],
])
->setLineEnding("\n");
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

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

## 1.0.0 - TBD
## 0.1.0

- initial release
- initial release
- action based mail sending with re-usable templates and sent mail tracking

## 1.0.0

- (new): Send pre-defined templates based on Model Events
- updated config
- cleaned up Vue structure

## Planned

- Tests
- Mail scheduling
- Additional tracking to help prevent duplicate mail sending
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
![banner](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/banner.png)
# An action based mail package for Nova apps
# Nova Mail

[![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)
[![Total Downloads](https://img.shields.io/packagist/dt/kirschbaum-development/nova-mail.svg?style=flat-square)](https://packagist.org/packages/kirschbaum-development/nova-mail)

This package contains a Nova action that provides a mail sending form for any resource to easily send email.
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.

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

![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)

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

![screenshot of mail template model events](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/mail-template-model-events.png)

## Requirements

This Nova package requires Nova 2.0 or higher.

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.

## Installation

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

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

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.

### Trigger Mail on Model Events

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:

![screenshot of the account status mail template](https://raw.githubusercontent.com/kirschbaum-development/nova-mail/master/screenshots/model-event-account-status-change.png)

You can even have separate Model Events for both "on" an "off"!

![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)

### Mail Template Usage/Caveats

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.
Expand Down Expand Up @@ -160,6 +176,7 @@ If you discover any security related issues, please email adam@kirschbaumdevelop
- [Adam Parker](https://github.com/adammparker)
- [Brandon Ferens](https://github.com/brandonferens)
- [Justin Seliga](https://github.com/jrseliga)
- [Belisar Hoxholli](https://github.com/belisarh)

## Sponsorship

Expand Down
29 changes: 18 additions & 11 deletions config/nova_mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,34 @@

/*
|--------------------------------------------------------------------------
| Keep Compiled File
| Show Resources
|--------------------------------------------------------------------------
|
| This deterimines if the compiled blade file used for sending the mail
| is kept on the file system after the mail has been delivered.
| This deterimines if the provided Nova resources
| are displayed in the Nova navigation menu.
|
*/

'keep_compiled_file' => false,
'show_resources' => [
'nova_sent_mail' => true,
'nova_mail_template' => true,
'nova_mail_event' => true,
],

/*
|--------------------------------------------------------------------------
| Show Resources
| Classes for dynamic event/column listening
|--------------------------------------------------------------------------
|
| This deterimines if the provided Nova resources
| are displayed in the Nova navigation menu.
| Here you can specify which classes can have dynamic
| listeners for sending Nova Mail Templates.
|
| Ex: [User::class]
|
| Note: These classes must use the Mailable trait and
| implement the abstract method getEmailField.
]
*/
'show_resources' => [
'nova_sent_mail' => true,
'nova_mail_template' => true,
],

'eventables' => [],
];
File renamed without changes.
1 change: 0 additions & 1 deletion dist/js/field.js

This file was deleted.

1 change: 1 addition & 0 deletions dist/js/fields.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/js/field.js": "/js/field.js",
"/css/field.css": "/css/field.css"
"/js/fields.js": "/js/fields.js",
"/css/fields.css": "/css/fields.css"
}
37 changes: 37 additions & 0 deletions migrations/2019_08_28_150259_create_nova_mail_events_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateNovaMailEventsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('nova_mail_events', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('mail_template_id');
$table->string('model');
$table->string('name');
$table->string('column')->nullable();
$table->string('value')->nullable();
$table->unsignedBigInteger('user_id');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('nova_mail_events');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddMailEventIdColumnToSentMailsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('nova_sent_mails', function (Blueprint $table) {
$table->unsignedBigInteger('mail_event_id')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('nova_sent_mails', function (Blueprint $table) {
$table->dropColumn('mail_event_id');
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AlterClolumnSenderIdOnSentMails extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('nova_sent_mails', function (Blueprint $table) {
$table->unsignedBigInteger('sender_id')->nullable()->change();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('nova_sent_mails', function (Blueprint $table) {
$table->unsignedBigInteger('sender_id')->change();
});
}
}
Loading

0 comments on commit c0a1c77

Please sign in to comment.