├── dist
├── css
│ └── tool.css
├── mix-manifest.json
└── js
│ └── tool.js
├── resources
├── sass
│ └── tool.scss
├── js
│ ├── components
│ │ └── Tool.vue
│ └── tool.js
└── views
│ └── navigation.blade.php
├── tool.png
├── webpack.mix.js
├── .gitignore
├── routes
└── api.php
├── src
├── NovaMailManager.php
├── Filters
│ ├── SentOnOrBeforeFilter.php
│ ├── SentOnOrAfterFilter.php
│ ├── MailableFilter.php
│ ├── StatusFilter.php
│ └── QueuedFilter.php
├── Http
│ └── Middleware
│ │ └── Authorize.php
├── Metrics
│ ├── EmailsByMailable.php
│ └── EmailsPerDay.php
├── Actions
│ └── ResendMail.php
├── NovaMailManagerServiceProvider.php
└── Resources
│ └── NovaMailResource.php
├── composer.json
├── package.json
├── LICENSE.md
└── README.md
/dist/css/tool.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/sass/tool.scss:
--------------------------------------------------------------------------------
1 | // Nova Tool CSS
2 |
--------------------------------------------------------------------------------
/tool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/binarybuilds/nova-mail-manager/HEAD/tool.png
--------------------------------------------------------------------------------
/dist/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/js/tool.js": "/js/tool.js",
3 | "/css/tool.css": "/css/tool.css"
4 | }
--------------------------------------------------------------------------------
/webpack.mix.js:
--------------------------------------------------------------------------------
1 | let mix = require('laravel-mix')
2 |
3 | mix.setPublicPath('dist')
4 | .js('resources/js/tool.js', 'js')
5 | .sass('resources/sass/tool.scss', 'css')
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /vendor
3 | /node_modules
4 | package-lock.json
5 | composer.phar
6 | composer.lock
7 | phpunit.xml
8 | .phpunit.result.cache
9 | .DS_Store
10 | Thumbs.db
11 |
--------------------------------------------------------------------------------
/resources/js/components/Tool.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/resources/js/tool.js:
--------------------------------------------------------------------------------
1 | Nova.booting((Vue, router, store) => {
2 | router.addRoutes([
3 | {
4 | name: 'nova-mail-manager',
5 | path: '/nova-mail-manager',
6 | component: require('./components/Tool'),
7 | },
8 | ])
9 | })
10 |
--------------------------------------------------------------------------------
/routes/api.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/NovaMailManager.php:
--------------------------------------------------------------------------------
1 | =7.1.0",
15 | "binarybuilds/laravel-mail-manager" : "^1.0"
16 | },
17 | "autoload": {
18 | "psr-4": {
19 | "BinaryBuilds\\NovaMailManager\\": "src/"
20 | }
21 | },
22 | "config": {
23 | "sort-packages": true
24 | },
25 | "minimum-stability": "dev",
26 | "prefer-stable": true
27 | }
28 |
--------------------------------------------------------------------------------
/src/Filters/SentOnOrBeforeFilter.php:
--------------------------------------------------------------------------------
1 | where('created_at', '<=', $value );
24 | }
25 |
26 | /**
27 | * @return array|null|string
28 | */
29 | public function name()
30 | {
31 | return __('Filter By Date(On Or Before)');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Filters/SentOnOrAfterFilter.php:
--------------------------------------------------------------------------------
1 | where('created_at', '>=', $value );
25 | }
26 |
27 | /**
28 | * @return array|null|string
29 | */
30 | public function name()
31 | {
32 | return __('Filter By Date(On Or After)');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Http/Middleware/Authorize.php:
--------------------------------------------------------------------------------
1 | first([$this, 'matchesTool']);
20 |
21 | return optional($tool)->authorize($request) ? $next($request) : abort(403);
22 | }
23 |
24 | /**
25 | * Determine whether this tool belongs to the package.
26 | *
27 | * @param \Laravel\Nova\Tool $tool
28 | * @return bool
29 | */
30 | public function matchesTool($tool)
31 | {
32 | return $tool instanceof NovaMailManager;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "npm run development",
5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
7 | "watch-poll": "npm run watch -- --watch-poll",
8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
9 | "prod": "npm run production",
10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
11 | },
12 | "devDependencies": {
13 | "cross-env": "^5.0.0",
14 | "laravel-mix": "^1.0"
15 | },
16 | "dependencies": {
17 | "vue": "^2.5.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Srinath Reddy Dudi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/src/Metrics/EmailsByMailable.php:
--------------------------------------------------------------------------------
1 | count($request, MailManagerMail::class, 'mailable_name');
22 | }
23 |
24 | /**
25 | * Determine for how many minutes the metric should be cached.
26 | *
27 | * @return \DateTimeInterface|\DateInterval|float|int
28 | */
29 | public function cacheFor()
30 | {
31 | // return now()->addMinutes(5);
32 | }
33 |
34 | /**
35 | * Get the URI key for the metric.
36 | *
37 | * @return string
38 | */
39 | public function uriKey()
40 | {
41 | return 'emails-by-mailable';
42 | }
43 |
44 | /**
45 | * @return array|null|string
46 | */
47 | public function name()
48 | {
49 | return __('Emails By Mailable');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Filters/MailableFilter.php:
--------------------------------------------------------------------------------
1 | where('mailable_name', $value);
29 | }
30 |
31 | /**
32 | * Get the filter's available options.
33 | *
34 | * @param \Illuminate\Http\Request $request
35 | * @return array
36 | */
37 | public function options(Request $request)
38 | {
39 | return MailManagerMail::groupBy('mailable_name')->pluck('mailable_name', 'mailable_name')->toArray();
40 | }
41 |
42 | /**
43 | * @return array|null|string
44 | */
45 | public function name()
46 | {
47 | return __('Filter By Mailable');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Actions/ResendMail.php:
--------------------------------------------------------------------------------
1 | count() . ' '. __('Mail(s) retried successfully'));
34 | }
35 |
36 | public function name()
37 | {
38 | return __('Resend Mail');
39 | }
40 |
41 | /**
42 | * Get the fields available on the action.
43 | *
44 | * @return array
45 | */
46 | public function fields()
47 | {
48 | return [];
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Filters/StatusFilter.php:
--------------------------------------------------------------------------------
1 | where('is_sent', true );
29 | } elseif ( $value === 'unsent') {
30 | return $query->where('is_sent', false );
31 | }
32 |
33 | return $query;
34 | }
35 |
36 | /**
37 | * Get the filter's available options.
38 | *
39 | * @param \Illuminate\Http\Request $request
40 | * @return array
41 | */
42 | public function options(Request $request)
43 | {
44 | return [
45 | 'Sent Emails' => 'sent',
46 | 'Unsent Emails' => 'unsent'
47 | ];
48 | }
49 |
50 | /**
51 | * @return array|null|string
52 | */
53 | public function name()
54 | {
55 | return __('Filter By Status');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Filters/QueuedFilter.php:
--------------------------------------------------------------------------------
1 | where('is_queued', true );
29 | } elseif ( $value === 'not-queued') {
30 | return $query->where('is_queued', false );
31 | }
32 |
33 | return $query;
34 | }
35 |
36 | /**
37 | * Get the filter's available options.
38 | *
39 | * @param \Illuminate\Http\Request $request
40 | * @return array
41 | */
42 | public function options(Request $request)
43 | {
44 | return [
45 | 'Queued Emails' => 'queued',
46 | 'Not Queued Emails' => 'not-queued'
47 | ];
48 | }
49 |
50 | /**
51 | * @return array|null|string
52 | */
53 | public function name()
54 | {
55 | return __('Filter By Queued Status');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Metrics/EmailsPerDay.php:
--------------------------------------------------------------------------------
1 | countByDays($request, MailManagerMail::class)->showLatestValue();
20 | }
21 |
22 | /**
23 | * Get the ranges available for the metric.
24 | *
25 | * @return array
26 | */
27 | public function ranges()
28 | {
29 | return [
30 | 7 => '1 '.__('Week'),
31 | 14 => '2 '.__('Weeks'),
32 | 30 => '30 '.__('Days'),
33 | 60 => '60 '.__('Days'),
34 | 90 => '90 '.__('Days'),
35 | ];
36 | }
37 |
38 | /**
39 | * Determine for how many minutes the metric should be cached.
40 | *
41 | * @return \DateTimeInterface|\DateInterval|float|int
42 | */
43 | public function cacheFor()
44 | {
45 | // return now()->addMinutes(5);
46 | }
47 |
48 | /**
49 | * Get the URI key for the metric.
50 | *
51 | * @return string
52 | */
53 | public function uriKey()
54 | {
55 | return 'emails-per-day';
56 | }
57 |
58 | /**
59 | * @return array|null|string
60 | */
61 | public function name()
62 | {
63 | return __('Emails Per Day');
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/NovaMailManagerServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadViewsFrom(__DIR__.'/../resources/views', 'nova-mail-manager');
22 |
23 | $this->app->register( \BinaryBuilds\LaravelMailManager\LaravelMailManagerServiceProvider::class );
24 |
25 | $this->app->booted(function () {
26 | $this->routes();
27 | });
28 |
29 | Nova::resources([
30 | NovaMailResource::class
31 | ]);
32 |
33 | Nova::serving(function (ServingNova $event) {
34 | //
35 | });
36 | }
37 |
38 | /**
39 | * Register the tool's routes.
40 | *
41 | * @return void
42 | */
43 | protected function routes()
44 | {
45 | if ($this->app->routesAreCached()) {
46 | return;
47 | }
48 |
49 | Route::middleware(['nova', Authorize::class])
50 | ->prefix('nova-vendor/nova-mail-manager')
51 | ->group(__DIR__.'/../routes/api.php');
52 | }
53 |
54 | /**
55 | * Register any application services.
56 | *
57 | * @return void
58 | */
59 | public function register()
60 | {
61 | //
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Resources/NovaMailResource.php:
--------------------------------------------------------------------------------
1 | onlyOnDetail(),
57 |
58 | Text::make(__('Mailable'), 'mailable_name'),
59 |
60 | Text::make(__('Subject'), 'subject'),
61 |
62 | Text::make(__('Recipients'), function (){
63 | return implode(', ', $this->recipients);
64 | }),
65 |
66 | Boolean::make(__('Is Queued'), 'is_queued'),
67 |
68 | Boolean::make(__('Is Sent'), 'is_sent'),
69 |
70 | Number::make(__('Tries'), 'tries'),
71 | ];
72 | }
73 |
74 | public function actions( Request $request )
75 | {
76 | return [
77 | new ResendMail
78 | ];
79 | }
80 |
81 | public function filters( Request $request )
82 | {
83 | return [
84 | new MailableFilter,
85 | new StatusFilter,
86 | new QueuedFilter,
87 | new SentOnOrAfterFilter,
88 | new SentOnOrBeforeFilter
89 | ];
90 | }
91 |
92 | public function cards( Request $request )
93 | {
94 | return [
95 | new EmailsPerDay,
96 | new EmailsByMailable
97 | ];
98 | }
99 |
100 | public static function label()
101 | {
102 | return __('Mails');
103 | }
104 |
105 | public static function singularLabel()
106 | {
107 | return __('Mail');
108 | }
109 |
110 | public static function uriKey()
111 | {
112 | return 'nova-mail-manager';
113 | }
114 |
115 | public static function authorizedToCreate(Request $request)
116 | {
117 | return false;
118 | }
119 |
120 | public function authorizedToUpdate( Request $request )
121 | {
122 | return false;
123 | }
124 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Nova Mail Manager
2 | ------------------------------------------------
3 | A [Laravel Nova](https://nova.laravel.com/) tool to easily resend your system generated emails without going through entire application flow.
4 |
5 | > Internally this package uses [Laravel Mail Manager](https://github.com/binarybuilds/laravel-mail-manager) to record and resend emails.
6 |
7 | 
8 |
9 | ### Installation
10 |
11 | This package can be installed using composer.
12 | ```bash
13 | composer require binarybuilds/nova-mail-manager
14 | ```
15 | Next you must register the package's service provider by adding the below line to `providers` array inside
16 | `config/app.php` file.
17 |
18 | ```php
19 | 'providers' => [
20 | //
21 | \BinaryBuilds\NovaMailManager\NovaMailManagerServiceProvider::class
22 | ]
23 | ```
24 |
25 | #### Conflicts With Laravel Telescope
26 | The dependent package([Laravel Mail Manager](https://github.com/binarybuilds/laravel-mail-manager)) currently conflicts
27 | with laravel telescope. If you are using laravel telescope in your application,
28 | Make sure you register the nova mail manager package's service provider after the telescope service provider is registered.
29 |
30 | If you are registering telescope using `config/app.php` file, Then add the service provider after the telescope service
31 | provider as shown below.
32 |
33 | ```php
34 | 'providers' => [
35 | //
36 | App\Providers\TelescopeServiceProvider::class,
37 | \BinaryBuilds\NovaMailManager\NovaMailManagerServiceProvider::class
38 | ]
39 | ```
40 |
41 | If you are registering telescope manually using `AppServiceProvider.php` file or any other service provider, Then register this package service
42 | provider after the telescope service provider is registered as shown below.
43 |
44 | ```php
45 | $this->app->register(TelescopeServiceProvider::class);
46 | $this->app->register(NovaMailManagerServiceProvider::class);
47 | ```
48 |
49 | Next, Publish the package configuration file by running
50 | ```bash
51 | php artisan vendor:publish --tag=laravel-mail-manager-config
52 | ```
53 | Run migrations to create the table required to store the emails.
54 | ```
55 | php artisan migrate
56 | ```
57 | This will create a table `mail_manager_mails`. You can configure the table name using the published configuration file
58 | located in `config/mail_manager.php`
59 |
60 | Next, Inside your `App/Providers/NovaServiceProvider.php` file, register the tool inside the `tools` method as shown below.
61 |
62 | ```php
63 | public function tools()
64 | {
65 | return [
66 | //
67 | new \BinaryBuilds\NovaMailManager\NovaMailManager()
68 | ];
69 | }
70 | ```
71 |
72 | ### Usage
73 | After installation, You will see `Mail Manager` in the nova navigation menu. Clicking on the link will take you to the
74 | tool page where you can view and resend mails.
75 |
76 | >The dependent package([Laravel Mail Manager](https://github.com/binarybuilds/laravel-mail-manager)) has few commands
77 | which you can use to manage mails. Checkout the readme file of [Laravel Mail Manager](https://github.com/binarybuilds/laravel-mail-manager)
78 | package for details.
79 |
80 | ## Contributing
81 |
82 | Thank you for considering contributing to Nova mail manager! Please create a pull request with your contributions with
83 | detailed explanation of the changes you are proposing.
84 |
85 | ## License
86 |
87 | This package is open-sourced software licensed under the [MIT license](LICENSE.md).
88 |
--------------------------------------------------------------------------------
/dist/js/tool.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){n(1),e.exports=n(11)},function(e,t,n){"use strict";Nova.booting(function(e,t,r){t.addRoutes([{name:"nova-mail-manager",path:"/nova-mail-manager",component:n(2)}])})},function(e,t,n){var r=n(8)(n(9),n(10),!1,function(e){n(3)},null,null);e.exports=r.exports},function(e,t,n){var r=n(4);"string"==typeof r&&(r=[[e.i,r,""]]),r.locals&&(e.exports=r.locals);n(6)("70658fb2",r,!0,{})},function(e,t,n){(e.exports=n(5)(!1)).push([e.i,"",""])},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(s=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(s))))+" */"),i=r.sources.map(function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"});return[n].concat(i).concat([o]).join("\n")}var s;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},o=0;on.parts.length&&(r.parts.length=n.parts.length)}else{var s=[];for(o=0;o