Merge branch 'master' into pr/21
This commit is contained in:
commit
21dff2d3e1
47 changed files with 5266 additions and 5914 deletions
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"printWidth": 120,
|
|
||||||
"semi": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"trailingComma": "es5"
|
|
||||||
}
|
|
1
Procfile
Normal file
1
Procfile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
web: vendor/bin/heroku-php-apache2 public/
|
|
@ -111,20 +111,20 @@ class ContactsController extends Controller
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
return Redirect::route('contacts.edit', $contact)->with('success', 'Contact updated.');
|
return Redirect::back()->with('success', 'Contact updated.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Contact $contact)
|
public function destroy(Contact $contact)
|
||||||
{
|
{
|
||||||
$contact->delete();
|
$contact->delete();
|
||||||
|
|
||||||
return Redirect::route('contacts.edit', $contact)->with('success', 'Contact deleted.');
|
return Redirect::back()->with('success', 'Contact deleted.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restore(Contact $contact)
|
public function restore(Contact $contact)
|
||||||
{
|
{
|
||||||
$contact->restore();
|
$contact->restore();
|
||||||
|
|
||||||
return Redirect::route('contacts.edit', $contact)->with('success', 'Contact restored.');
|
return Redirect::back()->with('success', 'Contact restored.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,20 +79,20 @@ class OrganizationsController extends Controller
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
return Redirect::route('organizations.edit', $organization)->with('success', 'Organization updated.');
|
return Redirect::back()->with('success', 'Organization updated.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Organization $organization)
|
public function destroy(Organization $organization)
|
||||||
{
|
{
|
||||||
$organization->delete();
|
$organization->delete();
|
||||||
|
|
||||||
return Redirect::route('organizations.edit', $organization)->with('success', 'Organization deleted.');
|
return Redirect::back()->with('success', 'Organization deleted.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restore(Organization $organization)
|
public function restore(Organization $organization)
|
||||||
{
|
{
|
||||||
$organization->restore();
|
$organization->restore();
|
||||||
|
|
||||||
return Redirect::route('organizations.edit', $organization)->with('success', 'Organization restored.');
|
return Redirect::back()->with('success', 'Organization restored.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ namespace App\Http\Controllers;
|
||||||
use App\User;
|
use App\User;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Request;
|
use Illuminate\Support\Facades\Request;
|
||||||
use Illuminate\Support\Facades\Redirect;
|
use Illuminate\Support\Facades\Redirect;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class UsersController extends Controller
|
class UsersController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -77,6 +79,10 @@ class UsersController extends Controller
|
||||||
|
|
||||||
public function update(User $user)
|
public function update(User $user)
|
||||||
{
|
{
|
||||||
|
if (App::environment('demo') && $user->isDemoUser()) {
|
||||||
|
return Redirect::back()->with('error', 'Updating the demo user is not allowed.');
|
||||||
|
}
|
||||||
|
|
||||||
Request::validate([
|
Request::validate([
|
||||||
'first_name' => ['required', 'max:50'],
|
'first_name' => ['required', 'max:50'],
|
||||||
'last_name' => ['required', 'max:50'],
|
'last_name' => ['required', 'max:50'],
|
||||||
|
@ -96,20 +102,24 @@ class UsersController extends Controller
|
||||||
$user->update(['password' => Request::get('password')]);
|
$user->update(['password' => Request::get('password')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::route('users.edit', $user)->with('success', 'User updated.');
|
return Redirect::back()->with('success', 'User updated.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(User $user)
|
public function destroy(User $user)
|
||||||
{
|
{
|
||||||
|
if (App::environment('demo') && $user->isDemoUser()) {
|
||||||
|
return Redirect::back()->with('error', 'Deleting the demo user is not allowed.');
|
||||||
|
}
|
||||||
|
|
||||||
$user->delete();
|
$user->delete();
|
||||||
|
|
||||||
return Redirect::route('users.edit', $user)->with('success', 'User deleted.');
|
return Redirect::back()->with('success', 'User deleted.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restore(User $user)
|
public function restore(User $user)
|
||||||
{
|
{
|
||||||
$user->restore();
|
$user->restore();
|
||||||
|
|
||||||
return Redirect::route('users.edit', $user)->with('success', 'User restored.');
|
return Redirect::back()->with('success', 'User restored.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@ class TrustProxies extends Middleware
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $proxies;
|
protected $proxies = '**';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The headers that should be used to detect proxies.
|
* The headers that should be used to detect proxies.
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $headers = Request::HEADER_X_FORWARDED_ALL;
|
protected $headers = Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
'flash' => function () {
|
'flash' => function () {
|
||||||
return [
|
return [
|
||||||
'success' => Session::get('success'),
|
'success' => Session::get('success'),
|
||||||
|
'error' => Session::get('error'),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
'errors' => function () {
|
'errors' => function () {
|
||||||
|
|
|
@ -42,6 +42,11 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isDemoUser()
|
||||||
|
{
|
||||||
|
return $this->email === 'johndoe@example.com';
|
||||||
|
}
|
||||||
|
|
||||||
public function scopeOrderByName($query)
|
public function scopeOrderByName($query)
|
||||||
{
|
{
|
||||||
$query->orderBy('last_name')->orderBy('first_name');
|
$query->orderBy('last_name')->orderBy('first_name');
|
||||||
|
|
|
@ -6,22 +6,22 @@
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2",
|
"php": "^7.2",
|
||||||
"fideloper/proxy": "^4.0",
|
"ext-exif": "*",
|
||||||
"inertiajs/inertia-laravel": "^0.1",
|
"ext-gd": "*",
|
||||||
"laravel/framework": "^6.0",
|
|
||||||
"laravel/tinker": "^1.0",
|
|
||||||
"league/glide": "2.0.x-dev",
|
|
||||||
"reinink/remember-query-strings": "^0.1.0",
|
|
||||||
"tightenco/ziggy": "^0.8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"barryvdh/laravel-debugbar": "^3.2",
|
"barryvdh/laravel-debugbar": "^3.2",
|
||||||
"beyondcode/laravel-dump-server": "^1.0",
|
"beyondcode/laravel-dump-server": "^1.0",
|
||||||
"facade/ignition": "^1.4",
|
"facade/ignition": "^1.4",
|
||||||
|
"fideloper/proxy": "^4.0",
|
||||||
"fzaninotto/faker": "^1.4",
|
"fzaninotto/faker": "^1.4",
|
||||||
|
"inertiajs/inertia-laravel": "^0.2",
|
||||||
|
"laravel/framework": "^6.0",
|
||||||
|
"laravel/tinker": "^1.0",
|
||||||
|
"league/glide": "2.0.x-dev",
|
||||||
"mockery/mockery": "^1.0",
|
"mockery/mockery": "^1.0",
|
||||||
"nunomaduro/collision": "^3.0",
|
"nunomaduro/collision": "^3.0",
|
||||||
"phpunit/phpunit": "^8.0"
|
"phpunit/phpunit": "^8.0",
|
||||||
|
"reinink/remember-query-strings": "^0.1.0",
|
||||||
|
"tightenco/ziggy": "^0.8.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"classmap": [
|
"classmap": [
|
||||||
|
@ -46,8 +46,8 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": [
|
"compile": [
|
||||||
"npm run prod",
|
"npm run prod",
|
||||||
"@php artisan vendor:publish --provider=\"Laravel\\Horizon\\HorizonServiceProvider\"",
|
"@php artisan migrate:fresh",
|
||||||
"@php artisan migrate --force"
|
"@php artisan db:seed"
|
||||||
],
|
],
|
||||||
"reseed": [
|
"reseed": [
|
||||||
"@php artisan migrate:fresh",
|
"@php artisan migrate:fresh",
|
||||||
|
|
6982
composer.lock
generated
6982
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -97,7 +97,21 @@ return [
|
||||||
'provider' => 'users',
|
'provider' => 'users',
|
||||||
'table' => 'password_resets',
|
'table' => 'password_resets',
|
||||||
'expire' => 60,
|
'expire' => 60,
|
||||||
|
'throttle' => 60,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Confirmation Timeout
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may define the amount of seconds before a password confirmation
|
||||||
|
| times out and the user is prompted to re-enter their password via the
|
||||||
|
| confirmation screen. By default, the timeout lasts for three hours.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'password_timeout' => 10800,
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -37,7 +37,7 @@ return [
|
||||||
'app_id' => env('PUSHER_APP_ID'),
|
'app_id' => env('PUSHER_APP_ID'),
|
||||||
'options' => [
|
'options' => [
|
||||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||||
'encrypted' => true,
|
'useTLS' => true,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ return [
|
||||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||||
|
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||||
],
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -35,6 +37,7 @@ return [
|
||||||
|
|
||||||
'sqlite' => [
|
'sqlite' => [
|
||||||
'driver' => 'sqlite',
|
'driver' => 'sqlite',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||||
'prefix' => '',
|
'prefix' => '',
|
||||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||||
|
@ -42,6 +45,7 @@ return [
|
||||||
|
|
||||||
'mysql' => [
|
'mysql' => [
|
||||||
'driver' => 'mysql',
|
'driver' => 'mysql',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
'host' => env('DB_HOST', '127.0.0.1'),
|
'host' => env('DB_HOST', '127.0.0.1'),
|
||||||
'port' => env('DB_PORT', '3306'),
|
'port' => env('DB_PORT', '3306'),
|
||||||
'database' => env('DB_DATABASE', 'forge'),
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
@ -61,6 +65,7 @@ return [
|
||||||
|
|
||||||
'pgsql' => [
|
'pgsql' => [
|
||||||
'driver' => 'pgsql',
|
'driver' => 'pgsql',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
'host' => env('DB_HOST', '127.0.0.1'),
|
'host' => env('DB_HOST', '127.0.0.1'),
|
||||||
'port' => env('DB_PORT', '5432'),
|
'port' => env('DB_PORT', '5432'),
|
||||||
'database' => env('DB_DATABASE', 'forge'),
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
@ -75,6 +80,7 @@ return [
|
||||||
|
|
||||||
'sqlsrv' => [
|
'sqlsrv' => [
|
||||||
'driver' => 'sqlsrv',
|
'driver' => 'sqlsrv',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
'host' => env('DB_HOST', 'localhost'),
|
'host' => env('DB_HOST', 'localhost'),
|
||||||
'port' => env('DB_PORT', '1433'),
|
'port' => env('DB_PORT', '1433'),
|
||||||
'database' => env('DB_DATABASE', 'forge'),
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
@ -113,13 +119,15 @@ return [
|
||||||
|
|
||||||
'redis' => [
|
'redis' => [
|
||||||
|
|
||||||
'client' => env('REDIS_CLIENT', 'predis'),
|
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||||
|
|
||||||
'options' => [
|
'options' => [
|
||||||
'cluster' => env('REDIS_CLUSTER', 'predis'),
|
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||||
|
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'default' => [
|
'default' => [
|
||||||
|
'url' => env('REDIS_URL'),
|
||||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||||
'password' => env('REDIS_PASSWORD', null),
|
'password' => env('REDIS_PASSWORD', null),
|
||||||
'port' => env('REDIS_PORT', 6379),
|
'port' => env('REDIS_PORT', 6379),
|
||||||
|
@ -127,6 +135,7 @@ return [
|
||||||
],
|
],
|
||||||
|
|
||||||
'cache' => [
|
'cache' => [
|
||||||
|
'url' => env('REDIS_URL'),
|
||||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||||
'password' => env('REDIS_PASSWORD', null),
|
'password' => env('REDIS_PASSWORD', null),
|
||||||
'port' => env('REDIS_PORT', 6379),
|
'port' => env('REDIS_PORT', 6379),
|
||||||
|
|
|
@ -37,7 +37,7 @@ return [
|
||||||
| may even configure multiple disks of the same driver. Defaults have
|
| may even configure multiple disks of the same driver. Defaults have
|
||||||
| been setup for each driver as an example of the required options.
|
| been setup for each driver as an example of the required options.
|
||||||
|
|
|
|
||||||
| Supported Drivers: "local", "ftp", "sftp", "s3", "rackspace"
|
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Monolog\Handler\NullHandler;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
use Monolog\Handler\SyslogUdpHandler;
|
use Monolog\Handler\SyslogUdpHandler;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ return [
|
||||||
'channels' => [
|
'channels' => [
|
||||||
'stack' => [
|
'stack' => [
|
||||||
'driver' => 'stack',
|
'driver' => 'stack',
|
||||||
'channels' => ['daily'],
|
'channels' => ['single'],
|
||||||
'ignore_exceptions' => false,
|
'ignore_exceptions' => false,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -89,6 +90,15 @@ return [
|
||||||
'driver' => 'errorlog',
|
'driver' => 'errorlog',
|
||||||
'level' => 'debug',
|
'level' => 'debug',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'null' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'handler' => NullHandler::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'emergency' => [
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -11,8 +11,8 @@ return [
|
||||||
| sending of e-mail. You may specify which one you're using throughout
|
| sending of e-mail. You may specify which one you're using throughout
|
||||||
| your application here. By default, Laravel is setup for SMTP mail.
|
| your application here. By default, Laravel is setup for SMTP mail.
|
||||||
|
|
|
|
||||||
| Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses",
|
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||||
| "sparkpost", "postmark", "log", "array"
|
| "postmark", "log", "array"
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ return [
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'failed' => [
|
'failed' => [
|
||||||
|
'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
|
||||||
'database' => env('DB_CONNECTION', 'mysql'),
|
'database' => env('DB_CONNECTION', 'mysql'),
|
||||||
'table' => 'failed_jobs',
|
'table' => 'failed_jobs',
|
||||||
],
|
],
|
||||||
|
|
|
@ -8,9 +8,9 @@ return [
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
|
||||||
| This file is for storing the credentials for third party services such
|
| This file is for storing the credentials for third party services such
|
||||||
| as Stripe, Mailgun, SparkPost and others. This file provides a sane
|
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||||
| default location for this type of information, allowing packages
|
| location for this type of information, allowing packages to have
|
||||||
| to have a conventional place to find your various credentials.
|
| a conventional file to locate the various service credentials.
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -30,18 +30,4 @@ return [
|
||||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'sparkpost' => [
|
|
||||||
'secret' => env('SPARKPOST_SECRET'),
|
|
||||||
],
|
|
||||||
|
|
||||||
'stripe' => [
|
|
||||||
'model' => App\User::class,
|
|
||||||
'key' => env('STRIPE_KEY'),
|
|
||||||
'secret' => env('STRIPE_SECRET'),
|
|
||||||
'webhook' => [
|
|
||||||
'secret' => env('STRIPE_WEBHOOK_SECRET'),
|
|
||||||
'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -18,7 +18,7 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'driver' => env('SESSION_DRIVER', 'file'),
|
'driver' => env('SESSION_DRIVER', 'cookie'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -190,7 +190,7 @@ return [
|
||||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||||
| do not enable this as other CSRF protection services are in place.
|
| do not enable this as other CSRF protection services are in place.
|
||||||
|
|
|
|
||||||
| Supported: "lax", "strict"
|
| Supported: "lax", "strict", "none"
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
3838
package-lock.json
generated
3838
package-lock.json
generated
File diff suppressed because it is too large
Load diff
29
package.json
29
package.json
|
@ -9,25 +9,24 @@
|
||||||
"prod": "npm run production",
|
"prod": "npm run production",
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"dependencies": {
|
||||||
|
"@fullhuman/postcss-purgecss": "^1.3.0",
|
||||||
"@inertiajs/inertia": "^0.1.7",
|
"@inertiajs/inertia": "^0.1.7",
|
||||||
"@inertiajs/inertia-vue": "^0.1.0",
|
"@inertiajs/inertia-vue": "^0.1.2",
|
||||||
"autosize": "^4.0.2",
|
"axios": "^0.18.1",
|
||||||
"axios": "^0.18",
|
"cross-env": "^5.2.1",
|
||||||
"cross-env": "^5.1",
|
"eslint": "^5.16.0",
|
||||||
"eslint": "^5.14.1",
|
"eslint-plugin-vue": "^5.2.3",
|
||||||
"eslint-plugin-vue": "^5.2.2",
|
"laravel-mix": "^5.0.1",
|
||||||
"fuse.js": "^3.4.6",
|
"lodash": "^4.17.15",
|
||||||
"laravel-mix": "^5.0.0",
|
|
||||||
"lodash": "^4.17.5",
|
|
||||||
"popper.js": "^1.16.0",
|
"popper.js": "^1.16.0",
|
||||||
"portal-vue": "^1.5.1",
|
"portal-vue": "^1.5.1",
|
||||||
"postcss-import": "^12.0.1",
|
"postcss-import": "^12.0.1",
|
||||||
"postcss-nesting": "^7.0.0",
|
"postcss-nesting": "^7.0.1",
|
||||||
"resolve-url-loader": "^2.3.1",
|
"resolve-url-loader": "^2.3.2",
|
||||||
"tailwindcss": "^1.0.1",
|
"tailwindcss": "^1.2.0-canary.5",
|
||||||
"vue": "^2.6.6",
|
"vue": "^2.6.11",
|
||||||
"vue-meta": "^2.3.1",
|
"vue-meta": "^2.3.1",
|
||||||
"vue-template-compiler": "^2.6.6"
|
"vue-template-compiler": "^2.6.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
resources/css/app.css
vendored
2
resources/css/app.css
vendored
|
@ -3,10 +3,10 @@
|
||||||
@import "reset";
|
@import "reset";
|
||||||
|
|
||||||
/* Components */
|
/* Components */
|
||||||
|
@import "tailwindcss/components";
|
||||||
@import "buttons";
|
@import "buttons";
|
||||||
@import "form";
|
@import "form";
|
||||||
@import "nprogress";
|
@import "nprogress";
|
||||||
@import "tailwindcss/components";
|
|
||||||
|
|
||||||
/* Utilities */
|
/* Utilities */
|
||||||
@import "tailwindcss/utilities";
|
@import "tailwindcss/utilities";
|
||||||
|
|
2
resources/css/buttons.css
vendored
2
resources/css/buttons.css
vendored
|
@ -1,4 +1,4 @@
|
||||||
.btn-indigo-500 {
|
.btn-indigo {
|
||||||
@apply px-6 py-3 rounded bg-indigo-600 text-white text-sm font-bold whitespace-no-wrap;
|
@apply px-6 py-3 rounded bg-indigo-600 text-white text-sm font-bold whitespace-no-wrap;
|
||||||
|
|
||||||
&:hover, &:focus { @apply bg-orange-500 }
|
&:hover, &:focus { @apply bg-orange-500 }
|
||||||
|
|
2
resources/css/form.css
vendored
2
resources/css/form.css
vendored
|
@ -10,7 +10,7 @@
|
||||||
&:focus,
|
&:focus,
|
||||||
&.focus {
|
&.focus {
|
||||||
@apply .border-indigo-500;
|
@apply .border-indigo-500;
|
||||||
box-shadow: 0 0 0 1px theme('colors.indigo-500');
|
box-shadow: 0 0 0 1px theme('colors.indigo.500');
|
||||||
}
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
|
|
5
resources/css/reset.css
vendored
5
resources/css/reset.css
vendored
|
@ -1,5 +1,6 @@
|
||||||
html {
|
a {
|
||||||
line-height: 1.15;
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input, select, textarea, button, div, a {
|
input, select, textarea, button, div, a {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="px-10 py-4 bg-gray-100 border-t border-gray-200 flex justify-between items-center">
|
<div class="px-10 py-4 bg-gray-100 border-t border-gray-200 flex justify-between items-center">
|
||||||
<a class="hover:underline" tabindex="-1" href="#reset-password">Forget password?</a>
|
<a class="hover:underline" tabindex="-1" href="#reset-password">Forget password?</a>
|
||||||
<loading-button :loading="sending" class="btn-indigo-500" type="submit">Login</loading-button>
|
<loading-button :loading="sending" class="btn-indigo" type="submit">Login</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,8 +41,8 @@ export default {
|
||||||
return {
|
return {
|
||||||
sending: false,
|
sending: false,
|
||||||
form: {
|
form: {
|
||||||
email: null,
|
email: 'johndoe@example.com',
|
||||||
password: null,
|
password: 'secret',
|
||||||
remember: null,
|
remember: null,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||||
</div>
|
</div>
|
||||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
||||||
<loading-button :loading="sending" class="btn-indigo-500" type="submit">Create Contact</loading-button>
|
<loading-button :loading="sending" class="btn-indigo" type="submit">Create Contact</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +41,7 @@ import TextInput from '@/Shared/TextInput'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Create Contact' },
|
metaInfo: { title: 'Create Contact' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
SelectInput,
|
SelectInput,
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||||
</div>
|
</div>
|
||||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
||||||
<button v-if="!contact.deleted_at" class="text-red-700 hover:underline" tabindex="-1" type="button" @click="destroy">Delete Contact</button>
|
<button v-if="!contact.deleted_at" class="text-red-600 hover:underline" tabindex="-1" type="button" @click="destroy">Delete Contact</button>
|
||||||
<loading-button :loading="sending" class="btn-indigo-500 ml-auto" type="submit">Update Contact</loading-button>
|
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update Contact</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,7 +51,7 @@ export default {
|
||||||
title: `${this.form.first_name} ${this.form.last_name}`,
|
title: `${this.form.first_name} ${this.form.last_name}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
SelectInput,
|
SelectInput,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<option value="only">Only Trashed</option>
|
<option value="only">Only Trashed</option>
|
||||||
</select>
|
</select>
|
||||||
</search-filter>
|
</search-filter>
|
||||||
<inertia-link class="btn-indigo-500" :href="route('contacts.create')">
|
<inertia-link class="btn-indigo" :href="route('contacts.create')">
|
||||||
<span>Create</span>
|
<span>Create</span>
|
||||||
<span class="hidden md:inline">Contact</span>
|
<span class="hidden md:inline">Contact</span>
|
||||||
</inertia-link>
|
</inertia-link>
|
||||||
|
@ -63,15 +63,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
|
||||||
import Icon from '@/Shared/Icon'
|
import Icon from '@/Shared/Icon'
|
||||||
import Layout from '@/Shared/Layout'
|
import Layout from '@/Shared/Layout'
|
||||||
|
import mapValues from 'lodash/mapValues'
|
||||||
import Pagination from '@/Shared/Pagination'
|
import Pagination from '@/Shared/Pagination'
|
||||||
|
import pickBy from 'lodash/pickBy'
|
||||||
import SearchFilter from '@/Shared/SearchFilter'
|
import SearchFilter from '@/Shared/SearchFilter'
|
||||||
|
import throttle from 'lodash/throttle'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Contacts' },
|
metaInfo: { title: 'Contacts' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
Pagination,
|
Pagination,
|
||||||
|
@ -91,8 +93,8 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
form: {
|
form: {
|
||||||
handler: _.throttle(function() {
|
handler: throttle(function() {
|
||||||
let query = _.pickBy(this.form)
|
let query = pickBy(this.form)
|
||||||
this.$inertia.replace(this.route('contacts', Object.keys(query).length ? query : { remember: 'forget' }))
|
this.$inertia.replace(this.route('contacts', Object.keys(query).length ? query : { remember: 'forget' }))
|
||||||
}, 150),
|
}, 150),
|
||||||
deep: true,
|
deep: true,
|
||||||
|
@ -100,7 +102,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
reset() {
|
reset() {
|
||||||
this.form = _.mapValues(this.form, () => null)
|
this.form = mapValues(this.form, () => null)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h1 class="mb-8 font-bold text-3xl">Dashboard</h1>
|
<h1 class="mb-8 font-bold text-3xl">Dashboard</h1>
|
||||||
<p class="mb-12 leading-normal">
|
<p class="mb-12 leading-normal">Hey there! Welcome to Ping CRM, a demo app designed to help illustrate how <a class="text-indigo-500 underline hover:text-orange-600" href="https://github.com/inertiajs">Inertia.js</a> works.</p>
|
||||||
Hey there! Welcome to Ping CRM, a demo app designed to help illustrate how
|
|
||||||
<a class="text-indigo-500 underline hover:text-orange-600" href="https://github.com/inertiajs">Inertia.js</a>
|
|
||||||
works.
|
|
||||||
</p>
|
|
||||||
<div>
|
<div>
|
||||||
<inertia-link class="btn-indigo-500" href="/500">500 error</inertia-link>
|
<inertia-link class="btn-indigo" href="/500">500 error</inertia-link>
|
||||||
<inertia-link class="btn-indigo-500" href="/404">404 error</inertia-link>
|
<inertia-link class="btn-indigo" href="/404">404 error</inertia-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||||
</div>
|
</div>
|
||||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
||||||
<loading-button :loading="sending" class="btn-indigo-500" type="submit">Create Organization</loading-button>
|
<loading-button :loading="sending" class="btn-indigo" type="submit">Create Organization</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +36,7 @@ import TextInput from '@/Shared/TextInput'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Create Organization' },
|
metaInfo: { title: 'Create Organization' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
SelectInput,
|
SelectInput,
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
<text-input v-model="form.postal_code" :errors="$page.errors.postal_code" class="pr-6 pb-8 w-full lg:w-1/2" label="Postal code" />
|
||||||
</div>
|
</div>
|
||||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
||||||
<button v-if="!organization.deleted_at" class="text-red-700 hover:underline" tabindex="-1" type="button" @click="destroy">Delete Organization</button>
|
<button v-if="!organization.deleted_at" class="text-red-600 hover:underline" tabindex="-1" type="button" @click="destroy">Delete Organization</button>
|
||||||
<loading-button :loading="sending" class="btn-indigo-500 ml-auto" type="submit">Update Organization</loading-button>
|
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update Organization</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -81,7 +81,7 @@ export default {
|
||||||
metaInfo() {
|
metaInfo() {
|
||||||
return { title: this.form.name }
|
return { title: this.form.name }
|
||||||
},
|
},
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<option value="only">Only Trashed</option>
|
<option value="only">Only Trashed</option>
|
||||||
</select>
|
</select>
|
||||||
</search-filter>
|
</search-filter>
|
||||||
<inertia-link class="btn-indigo-500" :href="route('organizations.create')">
|
<inertia-link class="btn-indigo" :href="route('organizations.create')">
|
||||||
<span>Create</span>
|
<span>Create</span>
|
||||||
<span class="hidden md:inline">Organization</span>
|
<span class="hidden md:inline">Organization</span>
|
||||||
</inertia-link>
|
</inertia-link>
|
||||||
|
@ -55,15 +55,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
|
||||||
import Icon from '@/Shared/Icon'
|
import Icon from '@/Shared/Icon'
|
||||||
import Layout from '@/Shared/Layout'
|
import Layout from '@/Shared/Layout'
|
||||||
|
import mapValues from 'lodash/mapValues'
|
||||||
import Pagination from '@/Shared/Pagination'
|
import Pagination from '@/Shared/Pagination'
|
||||||
|
import pickBy from 'lodash/pickBy'
|
||||||
import SearchFilter from '@/Shared/SearchFilter'
|
import SearchFilter from '@/Shared/SearchFilter'
|
||||||
|
import throttle from 'lodash/throttle'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Organizations' },
|
metaInfo: { title: 'Organizations' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
Pagination,
|
Pagination,
|
||||||
|
@ -83,8 +85,8 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
form: {
|
form: {
|
||||||
handler: _.throttle(function() {
|
handler: throttle(function() {
|
||||||
let query = _.pickBy(this.form)
|
let query = pickBy(this.form)
|
||||||
this.$inertia.replace(this.route('organizations', Object.keys(query).length ? query : { remember: 'forget' }))
|
this.$inertia.replace(this.route('organizations', Object.keys(query).length ? query : { remember: 'forget' }))
|
||||||
}, 150),
|
}, 150),
|
||||||
deep: true,
|
deep: true,
|
||||||
|
@ -92,7 +94,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
reset() {
|
reset() {
|
||||||
this.form = _.mapValues(this.form, () => null)
|
this.form = mapValues(this.form, () => null)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@ import Layout from '@/Shared/Layout'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Reports' },
|
metaInfo: { title: 'Reports' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<file-input v-model="form.photo" :errors="$page.errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
<file-input v-model="form.photo" :errors="$page.errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
||||||
</div>
|
</div>
|
||||||
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex justify-end items-center">
|
||||||
<loading-button :loading="sending" class="btn-indigo-500" type="submit">Create User</loading-button>
|
<loading-button :loading="sending" class="btn-indigo" type="submit">Create User</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@ import FileInput from '@/Shared/FileInput'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Create User' },
|
metaInfo: { title: 'Create User' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
SelectInput,
|
SelectInput,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="mb-8 flex justify-start max-w-lg">
|
<div class="mb-8 flex justify-start max-w-3xl">
|
||||||
<h1 class="font-bold text-3xl">
|
<h1 class="font-bold text-3xl">
|
||||||
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('users')">Users</inertia-link>
|
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('users')">Users</inertia-link>
|
||||||
<span class="text-indigo-400 font-medium">/</span>
|
<span class="text-indigo-400 font-medium">/</span>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
<trashed-message v-if="user.deleted_at" class="mb-6" @restore="restore">
|
<trashed-message v-if="user.deleted_at" class="mb-6" @restore="restore">
|
||||||
This user has been deleted.
|
This user has been deleted.
|
||||||
</trashed-message>
|
</trashed-message>
|
||||||
<div class="bg-white rounded shadow overflow-hidden max-w-lg">
|
<div class="bg-white rounded shadow overflow-hidden max-w-3xl">
|
||||||
<form @submit.prevent="submit">
|
<form @submit.prevent="submit">
|
||||||
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
|
||||||
<text-input v-model="form.first_name" :errors="$page.errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
<text-input v-model="form.first_name" :errors="$page.errors.first_name" class="pr-6 pb-8 w-full lg:w-1/2" label="First name" />
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
</select-input>
|
</select-input>
|
||||||
<file-input v-model="form.photo" :errors="$page.errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
<file-input v-model="form.photo" :errors="$page.errors.photo" class="pr-6 pb-8 w-full lg:w-1/2" type="file" accept="image/*" label="Photo" />
|
||||||
</div>
|
</div>
|
||||||
<div class="px-8 py-4 bg-grey-lightest border-t border-grey-lighter flex items-center">
|
<div class="px-8 py-4 bg-gray-100 border-t border-gray-200 flex items-center">
|
||||||
<button v-if="!user.deleted_at" class="text-red hover:underline" tabindex="-1" type="button" @click="destroy">Delete User</button>
|
<button v-if="!user.deleted_at" class="text-red-600 hover:underline" tabindex="-1" type="button" @click="destroy">Delete User</button>
|
||||||
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update User</loading-button>
|
<loading-button :loading="sending" class="btn-indigo ml-auto" type="submit">Update User</loading-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -47,7 +47,7 @@ export default {
|
||||||
title: `${this.form.first_name} ${this.form.last_name}`,
|
title: `${this.form.first_name} ${this.form.last_name}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
LoadingButton,
|
LoadingButton,
|
||||||
SelectInput,
|
SelectInput,
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<option value="only">Only Trashed</option>
|
<option value="only">Only Trashed</option>
|
||||||
</select>
|
</select>
|
||||||
</search-filter>
|
</search-filter>
|
||||||
<inertia-link class="btn-indigo-500" :href="route('users.create')">
|
<inertia-link class="btn-indigo" :href="route('users.create')">
|
||||||
<span>Create</span>
|
<span>Create</span>
|
||||||
<span class="hidden md:inline">User</span>
|
<span class="hidden md:inline">User</span>
|
||||||
</inertia-link>
|
</inertia-link>
|
||||||
|
@ -61,14 +61,16 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
|
||||||
import Icon from '@/Shared/Icon'
|
import Icon from '@/Shared/Icon'
|
||||||
import Layout from '@/Shared/Layout'
|
import Layout from '@/Shared/Layout'
|
||||||
|
import mapValues from 'lodash/mapValues'
|
||||||
|
import pickBy from 'lodash/pickBy'
|
||||||
import SearchFilter from '@/Shared/SearchFilter'
|
import SearchFilter from '@/Shared/SearchFilter'
|
||||||
|
import throttle from 'lodash/throttle'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo: { title: 'Users' },
|
metaInfo: { title: 'Users' },
|
||||||
layout: (h, page) => h(Layout, [page]),
|
layout: Layout,
|
||||||
components: {
|
components: {
|
||||||
Icon,
|
Icon,
|
||||||
SearchFilter,
|
SearchFilter,
|
||||||
|
@ -88,8 +90,8 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
form: {
|
form: {
|
||||||
handler: _.throttle(function() {
|
handler: throttle(function() {
|
||||||
let query = _.pickBy(this.form)
|
let query = pickBy(this.form)
|
||||||
this.$inertia.replace(this.route('users', Object.keys(query).length ? query : { remember: 'forget' }))
|
this.$inertia.replace(this.route('users', Object.keys(query).length ? query : { remember: 'forget' }))
|
||||||
}, 150),
|
}, 150),
|
||||||
deep: true,
|
deep: true,
|
||||||
|
@ -97,7 +99,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
reset() {
|
reset() {
|
||||||
this.form = _.mapValues(this.form, () => null)
|
this.form = mapValues(this.form, () => null)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<button type="button" @click="toggle">
|
<button type="button" @click="show = true">
|
||||||
<slot />
|
<slot />
|
||||||
<portal v-if="show" to="dropdown">
|
<portal v-if="show" to="dropdown">
|
||||||
<div>
|
<div>
|
||||||
<div style="position: fixed; top: 0; right: 0; left: 0; bottom: 0; z-index: 99998; background: black; opacity: .2" @click="toggle" />
|
<div style="position: fixed; top: 0; right: 0; left: 0; bottom: 0; z-index: 99998; background: black; opacity: .2" @click="show = false" />
|
||||||
<div ref="dropdown" style="position: absolute; z-index: 99999;" @click.stop>
|
<div ref="dropdown" style="position: absolute; z-index: 99999;" @click.stop="show = autoClose ? false : true">
|
||||||
<slot name="dropdown" />
|
<slot name="dropdown" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,6 +25,10 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'scrollParent',
|
default: 'scrollParent',
|
||||||
},
|
},
|
||||||
|
autoClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -50,17 +54,9 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.keyCode === 27) {
|
if (e.keyCode === 27) {
|
||||||
this.close()
|
this.show = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
close() {
|
|
||||||
this.show = false
|
|
||||||
},
|
|
||||||
toggle() {
|
|
||||||
this.show = !this.show
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
<div class="form-input p-0" :class="{ error: errors.length }">
|
<div class="form-input p-0" :class="{ error: errors.length }">
|
||||||
<input ref="file" type="file" :accept="accept" class="hidden" @change="change">
|
<input ref="file" type="file" :accept="accept" class="hidden" @change="change">
|
||||||
<div v-if="!value" class="p-2">
|
<div v-if="!value" class="p-2">
|
||||||
<button type="button" class="px-4 py-1 bg-grey-dark hover:bg-grey-darker rounded-sm text-xs font-medium text-white" @click="browse">
|
<button type="button" class="px-4 py-1 bg-gray-500 hover:bg-gray-700 rounded-sm text-xs font-medium text-white" @click="browse">
|
||||||
Browse
|
Browse
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="flex items-center justify-between p-2">
|
<div v-else class="flex items-center justify-between p-2">
|
||||||
<div class="flex-1 pr-1">{{ value.name }} <span class="text-grey-dark text-xs">({{ filesize(value.size) }})</span></div>
|
<div class="flex-1 pr-1">{{ value.name }} <span class="text-gray-500 text-xs">({{ filesize(value.size) }})</span></div>
|
||||||
<button type="button" class="px-4 py-1 bg-grey-dark hover:bg-grey-darker rounded-sm text-xs font-medium text-white" @click="remove">
|
<button type="button" class="px-4 py-1 bg-gray-500 hover:bg-gray-700 rounded-sm text-xs font-medium text-white" @click="remove">
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,17 +2,18 @@
|
||||||
<div>
|
<div>
|
||||||
<div v-if="$page.flash.success && show" class="mb-8 flex items-center justify-between bg-green-500 rounded max-w-3xl">
|
<div v-if="$page.flash.success && show" class="mb-8 flex items-center justify-between bg-green-500 rounded max-w-3xl">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<svg class="ml-4 mr-2 flex-no-shrink w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><polygon points="0 11 2 9 7 14 18 3 20 5 7 18" /></svg>
|
<svg class="ml-4 mr-2 flex-shrink-0 w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><polygon points="0 11 2 9 7 14 18 3 20 5 7 18" /></svg>
|
||||||
<div class="py-4 text-white text-sm font-medium">{{ $page.flash.success }}</div>
|
<div class="py-4 text-white text-sm font-medium">{{ $page.flash.success }}</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="group mr-2 p-2" @click="show = false">
|
<button type="button" class="group mr-2 p-2" @click="show = false">
|
||||||
<svg class="block w-2 h-2 fill-green-800 group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" width="235.908" height="235.908" viewBox="278.046 126.846 235.908 235.908"><path d="M506.784 134.017c-9.56-9.56-25.06-9.56-34.62 0L396 210.18l-76.164-76.164c-9.56-9.56-25.06-9.56-34.62 0-9.56 9.56-9.56 25.06 0 34.62L361.38 244.8l-76.164 76.165c-9.56 9.56-9.56 25.06 0 34.62 9.56 9.56 25.06 9.56 34.62 0L396 279.42l76.164 76.165c9.56 9.56 25.06 9.56 34.62 0 9.56-9.56 9.56-25.06 0-34.62L430.62 244.8l76.164-76.163c9.56-9.56 9.56-25.06 0-34.62z" /></svg>
|
<svg class="block w-2 h-2 fill-green-800 group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" width="235.908" height="235.908" viewBox="278.046 126.846 235.908 235.908"><path d="M506.784 134.017c-9.56-9.56-25.06-9.56-34.62 0L396 210.18l-76.164-76.164c-9.56-9.56-25.06-9.56-34.62 0-9.56 9.56-9.56 25.06 0 34.62L361.38 244.8l-76.164 76.165c-9.56 9.56-9.56 25.06 0 34.62 9.56 9.56 25.06 9.56 34.62 0L396 279.42l76.164 76.165c9.56 9.56 25.06 9.56 34.62 0 9.56-9.56 9.56-25.06 0-34.62L430.62 244.8l76.164-76.163c9.56-9.56 9.56-25.06 0-34.62z" /></svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="Object.keys($page.errors).length > 0 && show" class="mb-8 flex items-center justify-between bg-red-500 rounded max-w-3xl">
|
<div v-if="($page.flash.error || Object.keys($page.errors).length > 0) && show" class="mb-8 flex items-center justify-between bg-red-500 rounded max-w-3xl">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<svg class="ml-4 mr-2 flex-no-shrink w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z" /></svg>
|
<svg class="ml-4 mr-2 flex-shrink-0 w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z" /></svg>
|
||||||
<div class="py-4 text-white text-sm font-medium">
|
<div v-if="$page.flash.error" class="py-4 text-white text-sm font-medium">{{ $page.flash.error }}</div>
|
||||||
|
<div v-else class="py-4 text-white text-sm font-medium">
|
||||||
<span v-if="Object.keys($page.errors).length === 1">There is one form error.</span>
|
<span v-if="Object.keys($page.errors).length === 1">There is one form error.</span>
|
||||||
<span v-else>There are {{ Object.keys($page.errors).length }} form errors.</span>
|
<span v-else>There are {{ Object.keys($page.errors).length }} form errors.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-grow overflow-hidden">
|
<div class="flex flex-grow overflow-hidden">
|
||||||
<main-menu :url="url()" class="bg-indigo-800 flex-no-shrink w-56 p-12 hidden md:block overflow-y-auto" />
|
<main-menu :url="url()" class="bg-indigo-800 flex-shrink-0 w-56 p-12 hidden md:block overflow-y-auto" />
|
||||||
<div class="flex-1 overflow-hidden px-4 py-8 md:p-12 overflow-y-auto" scroll-region>
|
<div class="flex-1 overflow-hidden px-4 py-8 md:p-12 overflow-y-auto" scroll-region>
|
||||||
<flash-messages />
|
<flash-messages />
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="flex w-full bg-white shadow rounded">
|
<div class="flex w-full bg-white shadow rounded">
|
||||||
<dropdown class="px-4 md:px-6 rounded-l border-r hover:bg-gray-100 focus:border-white focus:shadow-outline focus:z-10" placement="bottom-start">
|
<dropdown :auto-close="false" class="px-4 md:px-6 rounded-l border-r hover:bg-gray-100 focus:border-white focus:shadow-outline focus:z-10" placement="bottom-start">
|
||||||
<div class="flex items-baseline">
|
<div class="flex items-baseline">
|
||||||
<span class="text-gray-700 hidden md:inline">Filter</span>
|
<span class="text-gray-700 hidden md:inline">Filter</span>
|
||||||
<svg class="w-2 h-2 fill-gray-600 md:ml-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 961.243 599.998">
|
<svg class="w-2 h-2 fill-gray-700 md:ml-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 961.243 599.998">
|
||||||
<path d="M239.998 239.999L0 0h961.243L721.246 240c-131.999 132-240.28 240-240.624 239.999-.345-.001-108.625-108.001-240.624-240z" />
|
<path d="M239.998 239.999L0 0h961.243L721.246 240c-131.999 132-240.28 240-240.624 239.999-.345-.001-108.625-108.001-240.624-240z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
</dropdown>
|
</dropdown>
|
||||||
<input class="relative w-full px-6 py-3 rounded-r focus:shadow-outline" autocomplete="off" type="text" name="search" placeholder="Search…" :value="value" @input="$emit('input', $event.target.value)">
|
<input class="relative w-full px-6 py-3 rounded-r focus:shadow-outline" autocomplete="off" type="text" name="search" placeholder="Search…" :value="value" @input="$emit('input', $event.target.value)">
|
||||||
</div>
|
</div>
|
||||||
<button class="ml-3 text-sm text-gray-500 hover:text-gray-600 focus:text-indigo-500" type="button" @click="$emit('reset')">Reset</button>
|
<button class="ml-3 text-sm text-gray-500 hover:text-gray-700 focus:text-indigo-500" type="button" @click="$emit('reset')">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import autosize from 'autosize'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: {
|
props: {
|
||||||
|
@ -24,15 +22,6 @@ export default {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
autosize: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.autosize) {
|
|
||||||
autosize(this.$refs.input)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
focus() {
|
focus() {
|
||||||
|
|
3
resources/js/app.js
vendored
3
resources/js/app.js
vendored
|
@ -13,8 +13,7 @@ let app = document.getElementById('app')
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
metaInfo: {
|
metaInfo: {
|
||||||
title: 'Loading…',
|
titleTemplate: (title) => title ? `${title} - Ping CRM` : 'Ping CRM'
|
||||||
titleTemplate: '%s | Ping CRM',
|
|
||||||
},
|
},
|
||||||
render: h => h(InertiaApp, {
|
render: h => h(InertiaApp, {
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -54,5 +54,10 @@ Route::get('reports')->name('reports')->uses('ReportsController')->middleware('a
|
||||||
|
|
||||||
// 500 error
|
// 500 error
|
||||||
Route::get('500', function () {
|
Route::get('500', function () {
|
||||||
|
// Force debug mode for this endpoint in the demo environment
|
||||||
|
if (App::environment('demo')) {
|
||||||
|
Config::set('app.debug', true);
|
||||||
|
}
|
||||||
|
|
||||||
echo $fail;
|
echo $fail;
|
||||||
});
|
});
|
||||||
|
|
21
webpack.mix.js
vendored
21
webpack.mix.js
vendored
|
@ -2,6 +2,8 @@ const cssImport = require('postcss-import')
|
||||||
const cssNesting = require('postcss-nesting')
|
const cssNesting = require('postcss-nesting')
|
||||||
const mix = require('laravel-mix')
|
const mix = require('laravel-mix')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const purgecss = require('@fullhuman/postcss-purgecss')
|
||||||
|
const tailwindcss = require('tailwindcss')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -14,9 +16,22 @@ const path = require('path')
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mix
|
mix.js('resources/js/app.js', 'public/js')
|
||||||
.js('resources/js/app.js', 'public/js')
|
.postCss('resources/css/app.css', 'public/css/app.css')
|
||||||
.postCss('resources/css/app.css', 'public/css', [cssImport(), cssNesting(), require('tailwindcss')])
|
.options({
|
||||||
|
postCss: [
|
||||||
|
cssImport(),
|
||||||
|
cssNesting(),
|
||||||
|
tailwindcss('tailwind.config.js'),
|
||||||
|
...mix.inProduction() ? [
|
||||||
|
purgecss({
|
||||||
|
content: ['./resources/views/**/*.blade.php', './resources/js/**/*.vue'],
|
||||||
|
defaultExtractor: content => content.match(/[\w-/:.]+(?<!:)/g) || [],
|
||||||
|
whitelistPatternsChildren: [/nprogress/],
|
||||||
|
}),
|
||||||
|
] : [],
|
||||||
|
],
|
||||||
|
})
|
||||||
.webpackConfig({
|
.webpackConfig({
|
||||||
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
|
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|
Loading…
Add table
Reference in a new issue