Confirmation Emails, Datatables (#2473)

* Fixes for MakesHash trait

* Client List DataTables

* Data table dependencies

* Confirmation URLs

* Wire up firing events for notification emails
This commit is contained in:
David Bomba 2018-10-29 14:16:17 +11:00 committed by GitHub
parent 849f6e5439
commit dde1cd6cfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1044 additions and 149 deletions

View File

@ -2,7 +2,12 @@
namespace App\Http\Controllers;
use App\Models\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Yajra\DataTables\Facades\DataTables;
use Yajra\DataTables\Html\Builder;
class ClientController extends Controller
{
@ -11,9 +16,45 @@ class ClientController extends Controller
*
* @return \Illuminate\Http\Response
*/
public function index()
public function index(Builder $builder)
{
Log::error('here i Am');
if (request()->ajax()) {
$clients = Client::select('clients.*', DB::raw("CONCAT(client_contacts.first_name,' ',client_contacts.last_name) as full_name"), 'client_contacts.email')
->leftJoin('client_contacts', function($leftJoin)
{
$leftJoin->on('clients.id', '=', 'client_contacts.client_id')
->where('client_contacts.is_primary', '=', true);
});
return DataTables::of($clients->get())
->addColumn('action', function ($client) {
return '<a href="#edit-'. $client->id .'" class="btn btn-xs btn-primary"><i class="glyphicon glyphicon-edit"></i> Edit</a>';
})
->addColumn('checkbox', function ($client){
return '<input type="checkbox" name="bulk" value="'. $client->id .'"/>';
})
->rawColumns(['checkbox', 'action'])
->make(true);
}
$builder->addAction();
$builder->addCheckbox();
$html = $builder->columns([
['data' => 'checkbox', 'name' => 'checkbox', 'title' => '', 'searchable' => false, 'orderable' => false],
['data' => 'name', 'name' => 'name', 'title' => trans('texts.name'), 'visible'=> true],
['data' => 'full_name', 'name' => 'full_name', 'title' => trans('texts.contact'), 'visible'=> true],
['data' => 'email', 'name' => 'email', 'title' => trans('texts.email'), 'visible'=> true],
['data' => 'created_at', 'name' => 'created_at', 'title' => trans('texts.date_created'), 'visible'=> true],
['data' => 'last_login', 'name' => 'last_login', 'title' => trans('texts.last_login'), 'visible'=> true],
['data' => 'balance', 'name' => 'balance', 'title' => trans('texts.balance'), 'visible'=> true],
['data' => 'action', 'name' => 'action', 'title' => '', 'searchable' => false, 'orderable' => false],
]);
return view('client.list', compact('html'));
}
/**
@ -81,4 +122,5 @@ class ClientController extends Controller
{
//
}
}

View File

@ -2,7 +2,7 @@
namespace App\Http\Controllers;
class HomeController extends Controller
class DashboardController extends Controller
{
/**
* Create a new controller instance.
@ -11,6 +11,7 @@ class HomeController extends Controller
*/
public function __construct()
{
$this->middleware('auth:user');
}
@ -21,13 +22,6 @@ class HomeController extends Controller
*/
public function index()
{
return view('home');
}
public function user()
{
$this->middleware('auth:user');
return view('dashboard.index');
}

View File

@ -3,6 +3,7 @@
namespace App\Http\Controllers\Traits;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
trait VerifiesUserEmail
{
@ -17,11 +18,13 @@ trait VerifiesUserEmail
$user->confirmation_code = null;
$user->save();
redirect()->route('user.dashboard')->with('message', trans('texts.security_confirmation'));
Auth::loginUsingId($user->id, true);
return redirect()->route('user.dashboard')->with('message', trans('texts.security_confirmation'));
}
redirect()->route('login')->with('message', trans('texts.wrong_confirmation'));
return redirect()->route('login')->with('message', trans('texts.wrong_confirmation'));
}
}

View File

@ -16,7 +16,7 @@ class UrlSetDb
* @return mixed
*/
public function handle($request, Closure $next, $hash)
public function handle($request, Closure $next)
{
if (config('ninja.db.multi_db_enabled'))
@ -24,11 +24,11 @@ class UrlSetDb
$hashids = new Hashids(); //decoded output is _always_ an array.
//parse URL hash and set DB
$segments = explode("-", $hash);
$segments = explode("-", $request->route('confirmation_code'));
$hashed_db = $hashids->decode($segments[0]);
MultiDB::setDB(MultiDB::DB_PREFIX . $hashed_db[0]);
MultiDB::setDB(MultiDB::DB_PREFIX . str_pad($hashed_db[0], 2 , "0", STR_PAD_LEFT));
}
return $next($request);

View File

@ -2,6 +2,7 @@
namespace App\Jobs\User;
use App\Events\User\UserCreated;
use App\Models\User;
use App\Models\UserCompany;
use App\Utils\Traits\MakesHash;
@ -62,6 +63,9 @@ class CreateUser
]);
event(new UserCreated($user));
return $user;
}
}

View File

@ -3,8 +3,10 @@
namespace App\Listeners;
use App\Libraries\MultiDB;
use App\Mail\VerifyUser;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Mail;
class SendVerificationNotification
{
@ -29,5 +31,9 @@ class SendVerificationNotification
//send confirmation email using $event->user
MultiDB::setDB($event->user->db);
Mail::to($event->user->email)
//->cc('')
//->bcc('')
->queue(new VerifyUser($event->user));
}
}

39
app/Mail/VerifyUser.php Normal file
View File

@ -0,0 +1,39 @@
<?php
namespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class VerifyUser extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('turbo124@gmail.com') //todo
->subject(__trans('texts.confirmation_subject'))
->markdown('email.auth.verify', ['user' => $this->user])
->text('email.auth.verify_text');
}
}

View File

@ -50,6 +50,10 @@ class Account extends Model
return $this->hasMany(Company::class);
}
public function default_company()
{
return $this->hasOne(Company::class, 'default_company_id', 'id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@ -6,5 +6,25 @@ use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
//
public function contacts()
{
return $this->hasMany(ClientContact::class);
}
public function locations()
{
return $this->hasMany(ClientLocation::class);
}
public function primary_location()
{
return $this->hasMany(ClientLocation::class)->whereIsPrimary(true);
}
public function primary_contact()
{
return $this->hasMany(ClientContact::class)->whereIsPrimary(true);
}
}

View File

@ -31,4 +31,10 @@ class ClientContact extends Authenticatable
'password', 'remember_token',
];
public function client()
{
$this->hasOne(Client::class);
}
}

View File

@ -6,5 +6,5 @@ use Illuminate\Database\Eloquent\Model;
class ClientLocation extends Model
{
//
public $timestamps = false;
}

View File

@ -44,7 +44,6 @@ class User extends Authenticatable implements MustVerifyEmail
*/
protected $hidden = [
'remember_token',
'confirmation_code',
'oauth_user_id',
'oauth_provider_id',
'google_2fa_secret',
@ -53,9 +52,14 @@ class User extends Authenticatable implements MustVerifyEmail
'slack_webhook_url',
];
public function user_accounts()
public function account()
{
return $this->hasMany(UserAccount::class);
return $this->hasOne(Account::class);
}
public function user_companies()
{
return $this->hasMany(UserCompany::class);
}
public function contacts()
@ -64,8 +68,6 @@ class User extends Authenticatable implements MustVerifyEmail
}
public function owns($entity)
{
return ! empty($entity->user_id) && $entity->user_id == $this->id;

View File

@ -4,8 +4,6 @@ namespace App\Providers;
use App\Events\User\UserCreated;
use App\Listeners\SendVerificationNotification;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
@ -16,9 +14,6 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
Registered::class => [
SendVerificationNotification::class,
],
UserCreated::class => [
SendVerificationNotification::class,
]

View File

@ -27,7 +27,7 @@ trait MakesHash
*/
public function createDbHash($db) : string
{
return getDbCode($db) . '-' . strtolower(str_random(RANDOM_KEY_LENGTH));
return $this->getDbCode($db) . '-' . strtolower(str_random(RANDOM_KEY_LENGTH));
}
/**

View File

@ -31,7 +31,9 @@
"predis/predis": "^1.1",
"spatie/laravel-html": "^2.19",
"webpatser/laravel-countries": "dev-master#75992ad",
"wildbit/postmark-php": "^2.6"
"wildbit/postmark-php": "^2.6",
"yajra/laravel-datatables": "^1.0",
"yajra/laravel-datatables-html": "^3.0"
},
"require-dev": {
"beyondcode/laravel-dump-server": "^1.0",

679
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f070f7f4ccfe346840e4dfd0e39650a5",
"content-hash": "753b0ff8fa34e1e5a54d950d3d780d30",
"packages": [
{
"name": "asgrim/ofxparser",
@ -1129,6 +1129,74 @@
],
"time": "2018-10-12T19:39:35+00:00"
},
{
"name": "laravelcollective/html",
"version": "v5.7.1",
"source": {
"type": "git",
"url": "https://github.com/LaravelCollective/html.git",
"reference": "777b6d390811ba249255ed5750bf17a019cd88a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/LaravelCollective/html/zipball/777b6d390811ba249255ed5750bf17a019cd88a5",
"reference": "777b6d390811ba249255ed5750bf17a019cd88a5",
"shasum": ""
},
"require": {
"illuminate/http": "5.7.*",
"illuminate/routing": "5.7.*",
"illuminate/session": "5.7.*",
"illuminate/support": "5.7.*",
"illuminate/view": "5.7.*",
"php": ">=7.1.3"
},
"require-dev": {
"illuminate/database": "5.7.*",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.7-dev"
},
"laravel": {
"providers": [
"Collective\\Html\\HtmlServiceProvider"
],
"aliases": {
"Form": "Collective\\Html\\FormFacade",
"Html": "Collective\\Html\\HtmlFacade"
}
}
},
"autoload": {
"psr-4": {
"Collective\\Html\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
},
{
"name": "Adam Engebretson",
"email": "adam@laravelcollective.com"
}
],
"description": "HTML and Form Builders for the Laravel Framework",
"homepage": "https://laravelcollective.com",
"time": "2018-09-05T18:32:53+00:00"
},
{
"name": "league/flysystem",
"version": "1.0.48",
@ -1213,6 +1281,70 @@
],
"time": "2018-10-15T13:53:10+00:00"
},
{
"name": "league/fractal",
"version": "0.17.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/fractal.git",
"reference": "a0b350824f22fc2fdde2500ce9d6851a3f275b0e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/fractal/zipball/a0b350824f22fc2fdde2500ce9d6851a3f275b0e",
"reference": "a0b350824f22fc2fdde2500ce9d6851a3f275b0e",
"shasum": ""
},
"require": {
"php": ">=5.4"
},
"require-dev": {
"doctrine/orm": "^2.5",
"illuminate/contracts": "~5.0",
"mockery/mockery": "~0.9",
"pagerfanta/pagerfanta": "~1.0.0",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5",
"zendframework/zend-paginator": "~2.3"
},
"suggest": {
"illuminate/pagination": "The Illuminate Pagination component.",
"pagerfanta/pagerfanta": "Pagerfanta Paginator",
"zendframework/zend-paginator": "Zend Framework Paginator"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.13-dev"
}
},
"autoload": {
"psr-4": {
"League\\Fractal\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Phil Sturgeon",
"email": "me@philsturgeon.uk",
"homepage": "http://philsturgeon.uk/",
"role": "Developer"
}
],
"description": "Handle the output of complex data structures ready for API output.",
"homepage": "http://fractal.thephpleague.com/",
"keywords": [
"api",
"json",
"league",
"rest"
],
"time": "2017-06-12T11:04:56+00:00"
},
{
"name": "league/oauth1-client",
"version": "1.7.0",
@ -1276,6 +1408,167 @@
],
"time": "2016-08-17T00:36:58+00:00"
},
{
"name": "maatwebsite/excel",
"version": "3.1.2",
"source": {
"type": "git",
"url": "https://github.com/Maatwebsite/Laravel-Excel.git",
"reference": "a80179c3f33d06fc0d7f22891d6aae4bb083f8c3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Maatwebsite/Laravel-Excel/zipball/a80179c3f33d06fc0d7f22891d6aae4bb083f8c3",
"reference": "a80179c3f33d06fc0d7f22891d6aae4bb083f8c3",
"shasum": ""
},
"require": {
"illuminate/support": "5.5.* || 5.6.* || 5.7.*",
"php": "^7.0",
"phpoffice/phpspreadsheet": "^1.4"
},
"require-dev": {
"mockery/mockery": "^1.1",
"orchestra/database": "^3.6",
"orchestra/testbench": "^3.6",
"phpunit/phpunit": "^7.0",
"predis/predis": "^1.1"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Maatwebsite\\Excel\\ExcelServiceProvider"
],
"aliases": {
"Excel": "Maatwebsite\\Excel\\Facades\\Excel"
}
}
},
"autoload": {
"psr-4": {
"Maatwebsite\\Excel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Patrick Brouwers",
"email": "patrick@maatwebsite.nl"
}
],
"description": "Supercharged Excel exports and imports in Laravel",
"keywords": [
"PHPExcel",
"batch",
"csv",
"excel",
"export",
"import",
"laravel",
"php",
"phpspreadsheet"
],
"time": "2018-10-11T09:21:58+00:00"
},
{
"name": "markbaker/complex",
"version": "1.4.7",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/1ea674a8308baf547cbcbd30c5fcd6d301b7c000",
"reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000",
"shasum": ""
},
"require": {
"php": "^5.6.0|^7.0.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3",
"phpcompatibility/php-compatibility": "^8.0",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "2.*",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^4.8.35|^5.4.0",
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "^3.3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
},
"files": [
"classes/src/functions/abs.php",
"classes/src/functions/acos.php",
"classes/src/functions/acosh.php",
"classes/src/functions/acot.php",
"classes/src/functions/acoth.php",
"classes/src/functions/acsc.php",
"classes/src/functions/acsch.php",
"classes/src/functions/argument.php",
"classes/src/functions/asec.php",
"classes/src/functions/asech.php",
"classes/src/functions/asin.php",
"classes/src/functions/asinh.php",
"classes/src/functions/atan.php",
"classes/src/functions/atanh.php",
"classes/src/functions/conjugate.php",
"classes/src/functions/cos.php",
"classes/src/functions/cosh.php",
"classes/src/functions/cot.php",
"classes/src/functions/coth.php",
"classes/src/functions/csc.php",
"classes/src/functions/csch.php",
"classes/src/functions/exp.php",
"classes/src/functions/inverse.php",
"classes/src/functions/ln.php",
"classes/src/functions/log2.php",
"classes/src/functions/log10.php",
"classes/src/functions/negative.php",
"classes/src/functions/pow.php",
"classes/src/functions/rho.php",
"classes/src/functions/sec.php",
"classes/src/functions/sech.php",
"classes/src/functions/sin.php",
"classes/src/functions/sinh.php",
"classes/src/functions/sqrt.php",
"classes/src/functions/tan.php",
"classes/src/functions/tanh.php",
"classes/src/functions/theta.php",
"classes/src/operations/add.php",
"classes/src/operations/subtract.php",
"classes/src/operations/multiply.php",
"classes/src/operations/divideby.php",
"classes/src/operations/divideinto.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"time": "2018-10-13T23:28:42+00:00"
},
{
"name": "monolog/monolog",
"version": "1.23.0",
@ -1636,6 +1929,93 @@
],
"time": "2018-07-02T15:55:56+00:00"
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "2dfd06c59825914a1a325f2a2ed13634b9d8c411"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/2dfd06c59825914a1a325f2a2ed13634b9d8c411",
"reference": "2dfd06c59825914a1a325f2a2ed13634b9d8c411",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"markbaker/complex": "^1.4.1",
"php": "^5.6|^7.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"dompdf/dompdf": "^0.8.0",
"friendsofphp/php-cs-fixer": "@stable",
"jpgraph/jpgraph": "^4.0",
"mpdf/mpdf": "^7.0.0",
"phpunit/phpunit": "^5.7",
"squizlabs/php_codesniffer": "^3.3",
"tecnickcom/tcpdf": "^6.2"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
"jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "http://blog.maartenballiauw.be"
},
{
"name": "Erik Tilt"
},
{
"name": "Franck Lefevre",
"homepage": "http://rootslabs.net"
},
{
"name": "Mark Baker",
"homepage": "http://markbakeruk.net"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"time": "2018-10-21T10:04:54+00:00"
},
{
"name": "predis/predis",
"version": "v1.1.1",
@ -3217,6 +3597,303 @@
],
"description": "The officially supported client for Postmark (http://postmarkapp.com)",
"time": "2018-07-24T22:40:23+00:00"
},
{
"name": "yajra/laravel-datatables",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/yajra/datatables.git",
"reference": "a5e2eaac3d7bc155502a37ab490cbcf0dee63e06"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yajra/datatables/zipball/a5e2eaac3d7bc155502a37ab490cbcf0dee63e06",
"reference": "a5e2eaac3d7bc155502a37ab490cbcf0dee63e06",
"shasum": ""
},
"require": {
"php": ">=7.0",
"yajra/laravel-datatables-buttons": "3.*|4.*",
"yajra/laravel-datatables-fractal": "1.*",
"yajra/laravel-datatables-html": "3.*",
"yajra/laravel-datatables-oracle": "8.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Arjay Angeles",
"email": "aqangeles@gmail.com"
}
],
"description": "Laravel DataTables Complete Package.",
"keywords": [
"datatables",
"jquery",
"laravel"
],
"time": "2018-08-15T12:31:12+00:00"
},
{
"name": "yajra/laravel-datatables-buttons",
"version": "v4.4.0",
"source": {
"type": "git",
"url": "https://github.com/yajra/laravel-datatables-buttons.git",
"reference": "649f0f6c02b391e349cff3f186aa88b61fb0cdd0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yajra/laravel-datatables-buttons/zipball/649f0f6c02b391e349cff3f186aa88b61fb0cdd0",
"reference": "649f0f6c02b391e349cff3f186aa88b61fb0cdd0",
"shasum": ""
},
"require": {
"illuminate/console": "^5.5",
"maatwebsite/excel": "^3.0",
"php": ">=7.0",
"yajra/laravel-datatables-html": "3.*",
"yajra/laravel-datatables-oracle": "8.*"
},
"require-dev": {
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~7.0"
},
"suggest": {
"barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view.",
"dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
},
"laravel": {
"providers": [
"Yajra\\DataTables\\ButtonsServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Yajra\\DataTables\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Arjay Angeles",
"email": "aqangeles@gmail.com"
}
],
"description": "Laravel DataTables Buttons Plugin.",
"keywords": [
"buttons",
"datatables",
"jquery",
"laravel"
],
"time": "2018-10-06T02:23:34+00:00"
},
{
"name": "yajra/laravel-datatables-fractal",
"version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/yajra/laravel-datatables-fractal.git",
"reference": "23804250ce32ddba216295ce47f713f551dba45c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yajra/laravel-datatables-fractal/zipball/23804250ce32ddba216295ce47f713f551dba45c",
"reference": "23804250ce32ddba216295ce47f713f551dba45c",
"shasum": ""
},
"require": {
"league/fractal": "^0.17.0",
"php": ">=7.0",
"yajra/laravel-datatables-oracle": "8.*"
},
"require-dev": {
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
},
"laravel": {
"providers": [
"Yajra\\DataTables\\FractalServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Yajra\\DataTables\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Arjay Angeles",
"email": "aqangeles@gmail.com"
}
],
"description": "Laravel DataTables Fractal Plugin.",
"keywords": [
"api",
"datatables",
"fractal",
"laravel"
],
"time": "2018-06-12T06:23:13+00:00"
},
{
"name": "yajra/laravel-datatables-html",
"version": "v3.8.0",
"source": {
"type": "git",
"url": "https://github.com/yajra/laravel-datatables-html.git",
"reference": "84a3b61e0ecba78108c55a508db150e8c8db2e59"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yajra/laravel-datatables-html/zipball/84a3b61e0ecba78108c55a508db150e8c8db2e59",
"reference": "84a3b61e0ecba78108c55a508db150e8c8db2e59",
"shasum": ""
},
"require": {
"laravelcollective/html": "^5.4",
"php": ">=7.0",
"yajra/laravel-datatables-oracle": "8.*"
},
"require-dev": {
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
},
"laravel": {
"providers": [
"Yajra\\DataTables\\HtmlServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Yajra\\DataTables\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Arjay Angeles",
"email": "aqangeles@gmail.com"
}
],
"description": "Laravel DataTables HTML builder plugin for Laravel 5.4+.",
"keywords": [
"JS",
"datatables",
"html",
"jquery",
"laravel"
],
"time": "2018-09-05T06:10:14+00:00"
},
{
"name": "yajra/laravel-datatables-oracle",
"version": "v8.9.1",
"source": {
"type": "git",
"url": "https://github.com/yajra/laravel-datatables.git",
"reference": "851c4d4d307a66a4f8ab5c12444c1eb0104ecc80"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yajra/laravel-datatables/zipball/851c4d4d307a66a4f8ab5c12444c1eb0104ecc80",
"reference": "851c4d4d307a66a4f8ab5c12444c1eb0104ecc80",
"shasum": ""
},
"require": {
"illuminate/database": "5.4.*|5.5.*|5.6.*|5.7.*",
"illuminate/filesystem": "5.4.*|5.5.*|5.6.*|5.7.*",
"illuminate/http": "5.4.*|5.5.*|5.6.*|5.7.*",
"illuminate/support": "5.4.*|5.5.*|5.6.*|5.7.*",
"illuminate/view": "5.4.*|5.5.*|5.6.*|5.7.*",
"php": ">=7.0"
},
"require-dev": {
"orchestra/testbench": "~3.5"
},
"suggest": {
"yajra/laravel-datatables-buttons": "Plugin for server-side exporting of dataTables.",
"yajra/laravel-datatables-editor": "Plugin to use DataTables Editor (requires a license).",
"yajra/laravel-datatables-fractal": "Plugin for server-side response using Fractal.",
"yajra/laravel-datatables-html": "Plugin for server-side HTML builder of dataTables."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.0-dev"
},
"laravel": {
"providers": [
"Yajra\\DataTables\\DataTablesServiceProvider"
],
"aliases": {
"DataTables": "Yajra\\DataTables\\Facades\\DataTables"
}
}
},
"autoload": {
"psr-4": {
"Yajra\\DataTables\\": "src/"
},
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Arjay Angeles",
"email": "aqangeles@gmail.com"
}
],
"description": "jQuery DataTables API for Laravel 4|5",
"keywords": [
"datatables",
"jquery",
"laravel"
],
"time": "2018-10-05T06:10:33+00:00"
}
],
"packages-dev": [

View File

@ -159,7 +159,8 @@ return [
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
Yajra\DataTables\DataTablesServiceProvider::class,
Yajra\DataTables\HtmlServiceProvider::class,
/*
* Dependency Service Providers
*/
@ -227,6 +228,7 @@ return [
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'Datatables' => Yajra\Datatables\Facades\Datatables::class,
/*
* Dependency Facades

View File

@ -0,0 +1,16 @@
<?php
return [
/*
* Default table attributes when generating the table.
*/
'table' => [
'class' => 'table',
'id' => 'table table-striped table-bordered',
],
/*
* Default condition to determine if a parameter is a callback or not
* Callbacks needs to start by those terms or they will be casted to string
*/
'callback' => ['$', '$.', 'function'],
];

View File

@ -13,12 +13,16 @@ use Faker\Generator as Faker;
|
*/
$factory->define(App\Models\Contact::class, function (Faker $faker) {
$factory->define(App\Models\ClientContact::class, function (Faker $faker) {
return [
'first_name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => bcrypt('secret'),
'remember_token' => str_random(10),
'db' => config('database.default')
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'phone' => $faker->phoneNumber,
'email_verified_at' => now(),
'email' => $faker->unique()->safeEmail,
'password' => bcrypt('password'),
'remember_token' => str_random(10),
'db' => config('database.default')
];
});

View File

@ -0,0 +1,19 @@
<?php
use Faker\Generator as Faker;
$factory->define(App\Models\Client::class, function (Faker $faker) {
return [
'name' => $faker->name(),
'website' => $faker->url,
'private_notes' => $faker->text(200),
'balance' => $faker->numberBetween(0,1000),
'paid_to_date' => $faker->numberBetween(0,10000),
'vat_number' => $faker->text(25),
'id_number' => $faker->text(20),
'custom_value1' => $faker->text(20),
'custom_value2' => $faker->text(20),
'payment_terms' => $faker->text(40),
];
});

View File

@ -0,0 +1,18 @@
<?php
use Faker\Generator as Faker;
$factory->define(App\Models\ClientLocation::class, function (Faker $faker) {
return [
'address1' => $faker->buildingNumber,
'address2' => $faker->streetAddress,
'city' => $faker->city,
'state' => $faker->state,
'postal_code' => $faker->postcode,
'country_id' => 4,
'latitude' => $faker->latitude,
'longitude' => $faker->longitude,
'description' => $faker->paragraph,
'private_notes' => $faker->paragraph
];
});

View File

@ -268,7 +268,7 @@ class CreateUsersTable extends Migration
$table->string('email',100);
$table->timestamp('email_verified_at')->nullable();
$table->string('confirmation_code')->nullable();
$table->boolean('registered')->default(false);
$table->boolean('is_primary')->default(false);
$table->boolean('confirmed')->default(false);
$table->smallInteger('failed_logins')->nullable();
$table->string('oauth_user_id',100)->nullable()->unique();

View File

@ -9,6 +9,7 @@ use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
use \App\Utils\Traits\MakesHash;
/**
* Run the database seeds.
*
@ -33,20 +34,17 @@ class UsersTableSeeder extends Seeder
$account->default_company_id = $company->id;
$account->save();
$user = User::create([
$user = factory(\App\Models\User::class)->create([
'account_id' => $account->id,
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'email' => config('ninja.testvars.username'),
'password' => Hash::make(config('ninja.testvars.password')),
'email_verified_at' => now(),
'confirmation_code' => $this->createDbHash(config('database.default'))
]);
$client = Client::create([
'name' => $faker->name,
'company_id' => $company->id,
$client = factory(\App\Models\Client::class)->create([
'user_id' => $user->id,
'company_id' => $company->id
]);
ClientContact::create([
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
@ -65,5 +63,34 @@ class UsersTableSeeder extends Seeder
'is_admin' => 1,
'is_locked' => 0,
]);
factory(\App\Models\Client::class, 50)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){
factory(\App\Models\ClientContact::class,1)->create([
'user_id' => $user->id,
'client_id' => $c->id,
'company_id' => $company->id,
'is_primary' => 1
]);
factory(\App\Models\ClientContact::class,10)->create([
'user_id' => $user->id,
'client_id' => $c->id,
'company_id' => $company->id
]);
factory(\App\Models\ClientLocation::class,1)->create([
'client_id' => $c->id,
'is_primary' => 1
]);
factory(\App\Models\ClientLocation::class,10)->create([
'client_id' => $c->id,
]);
});
}
}

View File

@ -0,0 +1,54 @@
@extends('layouts.master')
@section('head')
<link rel="stylesheet" href="//cdn.datatables.net/1.10.18/css/dataTables.bootstrap4.min.css">
<script src="//cdn.datatables.net/1.10.18/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/1.10.18/js/dataTables.bootstrap4.min.js"></script>
@endsection
@section('header')
@include('header')
@parent
@endsection
@section('sidebar')
@include('sidebar')
@endsection
@section('body')
<main class="main" >
<!-- Breadcrumb-->
{{ Breadcrumbs::render('clients') }}
<div class="container-fluid">
<div id="ui-view">
<div class="animated fadeIn">
<div class="row col-lg-12 card">
{!! $html->table() !!}
</div>
</div>
</div>
</div>
</main>
@include('dashboard.aside')
@endsection
@section('footer')
@include('footer')
{!! $html->scripts() !!}
@endsection

View File

@ -15,6 +15,9 @@
{{ Breadcrumbs::render('dashboard') }}
<div class="container-fluid">
</div>
</main>
@ -26,4 +29,3 @@
@include('footer')
@endsection

View File

@ -0,0 +1,35 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
Header Title
@endcomponent
@endslot
{{-- Body --}}
{{ $user }}
@lang('texts.confirmation_message')
@component('mail::button', ['url' => url("/user/confirm/{$user->confirmation_code} ")])
@lang('texts.confirm')
@endcomponent
{{-- Subcopy --}}
@isset($subcopy)
@slot('subcopy')
@component('mail::subcopy')
{{ $subcopy }}
@endcomponent
@endslot
@endisset
{{-- Footer --}}
@slot('footer')
@component('mail::footer')
© {{ date('Y') }} {{ config('ninja.app_name') }}.
@endcomponent
@endslot
@endcomponent

View File

@ -0,0 +1 @@
url("/user/confirm/{$user->confirmation_code}")

View File

@ -59,7 +59,7 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
<link rel="canonical" href="{{ config('ninja.site_url') }}/{{ request()->path() }}"/>
<link rel="stylesheet" href="{{ mix('/css/ninja.css') }}">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src=" {{ mix('/js/ninja.js') }}"></script>

View File

@ -9,7 +9,7 @@
</li>
<li class="nav-item">
<a class="nav-link" href="colors.html">
<a class="nav-link" href="/clients">
<i class="nav-icon icon-user"></i> @lang('texts.clients')</a>
</li>

View File

@ -1,96 +0,0 @@
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Nunito', sans-serif;
font-weight: 200;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.top-right {
position: absolute;
right: 10px;
top: 18px;
}
.content {
text-align: center;
}
.title {
font-size: 84px;
}
.links > a {
color: #636b6f;
padding: 0 25px;
font-size: 12px;
font-weight: 600;
letter-spacing: .1rem;
text-decoration: none;
text-transform: uppercase;
}
.m-b-md {
margin-bottom: 30px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@auth
<a href="{{ url('/home') }}">Home</a>
@else
<a href="{{ route('login') }}">Login</a>
<a href="{{ route('register') }}">Register</a>
@endauth
</div>
@endif
<div class="content">
<div class="title m-b-md">
Laravel
</div>
<div class="links">
<a href="https://laravel.com/docs">Documentation</a>
<a href="https://laracasts.com">Laracasts</a>
<a href="https://laravel-news.com">News</a>
<a href="https://nova.laravel.com">Nova</a>
<a href="https://forge.laravel.com">Forge</a>
<a href="https://github.com/laravel/laravel">GitHub</a>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,6 +1,12 @@
<?php
// Home
// Dashboard
Breadcrumbs::for('dashboard', function ($trail) {
$trail->push(trans('texts.dashboard'), route('user.dashboard'));
});
// Dashboard > Client
Breadcrumbs::for('clients', function ($trail) {
$trail->parent('dashboard');
$trail->push(trans('texts.clients'), route('clients.index'));
});

View File

@ -40,21 +40,25 @@ Route::get('auth/{provider}/callback', 'Auth\LoginController@handleProviderCallb
Route::group(['middleware' => ['auth:user', 'db']], function () {
Route::get('dashboard', 'HomeController@user')->name('user.dashboard');
Route::get('dashboard', 'DashboardController@index')->name('user.dashboard');
Route::get('logout', 'Auth\LoginController@logout')->name('user.logout');
Route::resource('invoices', 'InvoiceController'); // name = (invoices. index / create / show / update / destroy / edit
Route::resource('clients', 'ClientController'); // name = (clients. index / create / show / update / destroy / edit
Route::get('settings', 'SettingsController@index')->name('user.settings');
});
/*
* Inbound routes requiring DB Lookup
*/
Route::group(['middleware' => ['auth:user', 'db']], function () {
Route::group(['middleware' => ['url-db']], function () {
Route::get('/user/confirm/{confirmation_code}', 'UserController@confirm');
});
/*
Authenticated Contact Routes
*/
@ -66,3 +70,12 @@ Route::group(['prefix' => 'contact', 'middleware' => 'auth:contact'], function
});
/* Dev Playground
Route::get('/mailable', function () {
$user = App\Models\User::find(1);
return new App\Mail\VerifyUser($user);
});
*/