This commit is contained in:
Ryan Scherler
2020-10-16 13:17:09 -07:00
parent 39b017f62a
commit f5e5467005
32 changed files with 15195 additions and 179 deletions
+3
View File
@@ -0,0 +1,3 @@
# BrowserSync
# BROWSERSYNC_PROXY='http://127.0.0.1:8000'
# BROWSERSYNC_HTTPS=false
+6 -3
View File
@@ -1,4 +1,7 @@
/vendor
/vendor/
/node_modules/
SCRATCH.md
COMMIT_MSG.aim.txt
composer.lock
/phpunit.xml
.phpunit.result.cache
.phpunit.result.cache
.idea
Executable
+6
View File
@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true
}
+2 -10
View File
@@ -1,13 +1,5 @@
# Filament
Extend Laravel Jetstream with Filament.
A lightweight admin for your Laravel app.
## Features
### User management
- [ ] Register new users from within Jetstream.
#### Permissions
- [ ] User permissions not bound to teams for more granular access control.
> This is a new version that is very much a work in progress!
+7 -5
View File
@@ -1,11 +1,10 @@
{
"name": "filament/filament",
"description": "Extend Laravel Jetstream with Filament.",
"keywords": ["laravel", "laravel-jetstream", "tailwind", "livewire"],
"description": "A lightweight admin for your Laravel app.",
"keywords": ["laravel", "tailwind", "livewire"],
"license": "MIT",
"require": {
"laravel/jetstream": "^1.1",
"livewire/livewire": "^2.0"
"livewire/livewire": "^2.2"
},
"require-dev": {
"mockery/mockery": "^1.0",
@@ -26,7 +25,10 @@
"laravel": {
"providers": [
"Filament\\FilamentServiceProvider"
]
],
"aliases": {
"Filament": "Filament\\FilamentFacade"
}
}
},
"scripts": {
+74 -16
View File
@@ -3,32 +3,90 @@
use Filament\Features;
return [
/*
|--------------------------------------------------------------------------
| Filament Stack
|--------------------------------------------------------------------------
|
| This configuration value informs Filament which "stack" you will be
| using for Jetstream. Livewire is currently the only available
| stack for this package.
|
*/
'stack' => 'livewire',
/*
|--------------------------------------------------------------------------
| Features
|--------------------------------------------------------------------------
|
| By default all of Filament's features are optional. You may enable
| features as needed by your application.
| By default all of Filament's features are enabled. You may enable
| or disable features as needed by your application.
|
*/
'features' => [
Features::managesUsers(),
Features::users(),
],
'prefix' => [
/*
|--------------------------------------------------------------------------
| Route Name Prefix
|--------------------------------------------------------------------------
|
| This value will set a prefix for all Filament route names.
|
*/
'name' => 'filament.',
/*
|--------------------------------------------------------------------------
| Route Prefix
|--------------------------------------------------------------------------
|
| This value will set a prefix for all Filament routes.
|
*/
'route' => 'filament',
/*
|--------------------------------------------------------------------------
| Component Prefix
|--------------------------------------------------------------------------
|
| This value will set a prefix for all Filament components.
|
| If set with the default "filament", for example, you can reference components like:
|
| <x-filament-alert />
| <x-filament::input />
|
*/
'component' => 'filament',
],
/*
|--------------------------------------------------------------------------
| Components
|--------------------------------------------------------------------------
|
| Below you reference all components that should be loaded for your app.
| By default all components from Filament are loaded in. You can
| disable or overwrite any component class or alias that you want.
|
*/
'components' => [
//...
],
/*
|--------------------------------------------------------------------------
| Livewire Components
|--------------------------------------------------------------------------
|
| Below you reference all the Livewire components that should be loaded
| for your app. By default all components from Filament are loaded in.
|
*/
'livewire' => [
'login' => Filament\Http\Livewire\Auth\Login::class,
],
];
+2
View File
@@ -0,0 +1,2 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button{-webkit-appearance:button}button::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}details{display:block}summary{display:list-item}template{display:none}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:transparent;background-image:none}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#a0aec0}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#a0aec0}input::placeholder,textarea::placeholder{color:#a0aec0}button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}.table{display:table}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}@-webkit-keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{50%{opacity:.5}}@keyframes pulse{50%{opacity:.5}}@-webkit-keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}
/*# sourceMappingURL=filament.css.map*/
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./node_modules/tailwindcss/base.css","webpack:///./node_modules/tailwindcss/utilities.css"],"names":[],"mappings":"AAAA,+HAAc,CAAd,aAAc,CAAd,kBAAc,CAAd,+BAAc,CAAd,mDAAc,CAAd,iDAAc,CAAd,8BAAc,CAAd,kIAAc,CAAd,2BAAc,CAAd,2DAAc,CAAd,mBAAc,CAAd,6EAAc,CAAd,iBAAc,CAAd,aAAc,CAAd,qBAAc,CAAd,kGAAc,CAAd,6BAAc,CAAd,iCAAc,CAAd,gCAAc,CAAd,oDAAc,CAAd,mDAAc,CAAd,mCAAc,CAAd,oGAAc,CAAd,gCAAc,CAAd,sBAAc,CAAd,qBAAc,CAAd,yBAAc,CAAd,qBAAc,CAAd,2DAAc,CAAd,yDAAc,CAAd,yEAAc,CAAd,iCAAc,CAAd,qBAAc,CAAd,uMAAc,CAAd,6DAAc,CAAd,uBAAc,CAAd,sBAAc,CAAd,wBAAc,CAAd,gEAAc,CAAd,wEAAc,CAAd,sDAAc,CAAd,qBAAc,CAAd,8BAAc,CAAd,uDAAc,CAAd,uCAAc,CAAd,iFAAc,CAAd,yFAAc,CAAd,kFAAc,CAAd,oCAAc,CCAd,oBAAmB,CAAnB,kDAAmB,EAAnB,0CAAmB,EAAnB,2DAAmB,EAAnB,mDAAmB,EAAnB,uCAAmB,EAAnB,+BAAmB,EAAnB,oKAAmB,CAAnB,4HAAmB,EAAnB,4JAAmB,CAAnB,4HAAmB","file":"css/filament.css","sourcesContent":["@tailwind base;\n","@tailwind utilities;\n"],"sourceRoot":""}
+2
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
{
"/js/filament.js": "/js/filament.js?id=1faaac0d122aa02f8bf6",
"/css/filament.css": "/css/filament.css?id=a88feaa8e5c631116abb",
"/js/filament.js.map": "/js/filament.js.map?id=7eb1b0da03c81ab3ba1b",
"/css/filament.css.map": "/css/filament.css.map?id=96617d0d1a6152e58710"
}
+14574
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
{
"name": "filament",
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run development -- --watch",
"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",
"start": "npm run watch"
},
"author": {
"name": "Ryan Scherler",
"email": "ryan@eastslope.studio"
},
"license": "MIT",
"devDependencies": {
"browser-sync": "^2.26.12",
"browser-sync-webpack-plugin": "^2.2.2",
"cross-env": "^7.0.2",
"dotenv": "^8.2.0",
"laravel-mix": "^5.0.7",
"postcss-import": "^12.0.1",
"postcss-nested": "^4.2.3",
"prettier": "^2.1.2",
"tailwindcss": "^1.9.3",
"vue-template-compiler": "^2.6.12"
},
"dependencies": {
"alpinejs": "^2.7.0",
"focus-visible": "^5.1.0"
}
}
+9
View File
@@ -0,0 +1,9 @@
@layer base {
/*
This will hide the focus indicator if the element receives focus via the mouse,
but it will still show up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
outline: none;
}
}
+7
View File
@@ -0,0 +1,7 @@
@import 'tailwindcss/base';
@import './base.css';
@import 'tailwindcss/components';
/* @import './components/button.css'; */
@import 'tailwindcss/utilities';
+2
View File
@@ -0,0 +1,2 @@
import 'focus-visible'
import 'alpinejs'
@@ -1,11 +0,0 @@
<div class="block px-4 py-2 text-xs text-gray-400">
{{ __('Manage Users') }}
</div>
@can('create', Laravel\Jetstream\Jetstream::newUserModel())
<x-jet-dropdown-link href="/users/create">
{{ __('Create New User') }}
</x-jet-dropdown-link>
@endcan
<div class="border-t border-gray-100"></div>
+20
View File
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
@filamentStyles
@livewireStyles
@stack('head')
</head>
<body>
<main>
{{ $slot }}
</main>
@filamentScripts
@livewireScripts
@stack('scripts')
</body>
</html>
+1
View File
@@ -0,0 +1 @@
<div>login form...</div>
+47
View File
@@ -0,0 +1,47 @@
<?php
use Illuminate\Support\Facades\Route;
use Filament\Features;
use Filament\Http\Controllers\{
AssetController,
};
$routeNamePrefix = config('filament.prefix.name', 'filament.');
Route::group([
'prefix' => config('filament.prefix.route'),
'middleware' => config('filament.middleware', ['web']),
'as' => $routeNamePrefix,
], function () use ($routeNamePrefix) {
// Assets
Route::name('assets.')->group(function () {
Route::get('filament.css', [AssetController::class, 'css'])->name('css');
Route::get('filament.css.map', [AssetController::class, 'cssMap']);
Route::get('filament.js', [AssetController::class, 'js'])->name('js');
Route::get('filament.js.map', [AssetController::class, 'jsMap']);
});
// Auth
Route::get('/login', config('filament.livewire.login'))->name('login');
// Authenticated routes
Route::group(['middleware' => ['auth', 'verified']], function () {
// User profile
Route::get('/profile', config('filament.livewire.profile'))->name('profile');
// Users
if (Features::managesUsers()) {
Route::name('users.')->group(function () {
Route::get('/users', config('filament.livewire.users'))->name('index');
Route::get('/user/{user}', config('filament.livewire.user'))->name('show');
});
}
});
});
// Conditional route login alias
if (!Route::has('login')) {
Route::get('/login', function () use ($routeNamePrefix) {
return redirect()->route("{$routeNamePrefix}login");
})->name('login');
}
-18
View File
@@ -1,18 +0,0 @@
<?php
use Illuminate\Support\Facades\Route;
use Laravel\Jetstream\Jetstream;
Route::group(['middleware' => config('filament.middleware.web', ['web'])], function () {
Route::group(['middleware' => ['auth', 'verified']], function () {
// API...
if (Jetstream::hasApiFeatures()) {
}
// Teams...
if (Jetstream::hasTeamFeatures()) {
}
});
});
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Filament;
class BladeDirectives
{
public static function styles(): string
{
return '{!! \Filament::styles() !!}';
}
public static function scripts(): string
{
return '{!! \Filament::scripts() !!}';
}
}
+5 -5
View File
@@ -16,21 +16,21 @@ class Features
}
/**
* Determine if the application is using any user features.
* Determine if the application manages users.
*
* @return bool
*/
public static function hasUserManagementFeatures()
public static function managesUsers()
{
return static::enabled(static::managesUsers());
return static::enabled(static::users());
}
/**
* Enable the user management feature.
* Enable the users feature.
*
* @return string
*/
public static function managesUsers()
public static function users()
{
return 'users';
}
+97 -6
View File
@@ -2,7 +2,10 @@
namespace Filament;
class Filament
use Illuminate\Support\Facades\Request;
use Illuminate\Support\HtmlString;
class Filament
{
/**
* Indicates if Filament routes will be registered.
@@ -16,20 +19,108 @@ class Filament
*
* @return static
*/
public static function ignoreRoutes()
public function ignoreRoutes()
{
static::$registersRoutes = false;
return new static;
}
/**
* `base` path
*
* @param string $path
* @return string
*/
public function basePath($path = '')
{
return __DIR__.'/../'.ltrim($path, '/');
}
/**
* Determine if Filament is supporting user management features.
* `dist` path
*
* @return bool
* @param string $path
* @return string
*/
public static function hasUserManagementFeatures()
public function distPath($path = '')
{
return Features::hasUserManagementFeatures();
return $this->basePath('dist/'.ltrim($path, '/'));
}
public function handling(): boolean
{
return preg_match('#^'.config('filament.prefix.route').'($|/)'.'#i', Request::path());
}
public function styles(): HtmlString
{
$key = '/css/filament.css';
$asset = $this->getAsset($key);
$publishedAsset = $this->getPublicAsset($key);
if ($publishedAsset) {
$assetWarning = ($publishedAsset !== $asset) ?
'<script>console.warn("Filament: The published style assets are out of date.\n");</script>' : null;
return new HtmlString("
<!-- Filament Published Styles -->
{$assetWarning}
<link rel=\"stylesheet\" href=\"/vendor/filament{$publishedAsset}\">
");
}
parse_str(parse_url($asset, PHP_URL_QUERY), $cssInfo);
$src = route('filament.assets.css', $cssInfo);
return new HtmlString('
<!-- Filament Styles -->
<link rel="stylesheet" href="'.$src.'">
');
}
public function scripts(): Htmlstring
{
$key = '/js/filament.js';
$asset = $this->getAsset($key);
$publishedAsset = $this->getPublicAsset($key);
if ($publishedAsset) {
$assetWarning = ($publishedAsset !== $asset) ?
'<script>console.warn("Filament: The published javascript assets are out of date.\n");</script>' : null;
return new HtmlString("
<!-- Filament Published Scripts -->
{$assetWarning}
<script src=\"/vendor/filament{$publishedAsset}\" data-turbolinks-eval=\"false\"></script>
");
}
parse_str(parse_url($asset, PHP_URL_QUERY), $jsInfo);
$src = route('filament.assets.js', $jsInfo);
return new HtmlString('
<!-- Filament Scripts -->
<script src="'.$src.'" data-turbolinks-eval="false"></script>
');
}
protected function getAsset($key): string
{
$manifest = json_decode(file_get_contents($this->distPath('mix-manifest.json')), true);
return $manifest[$key];
}
/** @return mixed */
protected function getPublicAsset($key)
{
if (!file_exists(public_path('vendor/filament/mix-manifest.json'))) {
return;
}
$manifest = json_decode(file_get_contents(public_path('vendor/filament/mix-manifest.json')), true);
return $manifest[$key];
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Filament;
use Illuminate\Support\Facades\Facade;
class FilamentFacade extends Facade
{
/**
* {@inheritDoc}
*/
protected static function getFacadeAccessor()
{
return Filament::class;
}
}
+58 -82
View File
@@ -3,89 +3,72 @@
namespace Filament;
use Illuminate\Support\ServiceProvider;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\Support\Facades\{
Route,
Gate,
Blade,
};
use Illuminate\Support\Str;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Finder\SplFileInfo;
use Livewire\{
Livewire,
Component,
};
use Livewire\Livewire;
class FilamentServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
public function register(): void
{
$this->mergeConfigFrom(__DIR__.'/../config/filament.php', 'filament');
$this->registerFacade();
$this->registerLivewireComponents();
}
/**
* Bootstrap any package services.
*
* @return void
*/
public function boot()
public function boot(): void
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'filament');
$this->configurePolicies();
$this->configureComponents();
$this->configureLivewireComponents();
$this->configurePublishing();
$this->configureRoutes();
$this->bootPolicies();
$this->bootResources();
$this->bootDirectives();
$this->bootRoutes();
$this->bootCommands();
$this->bootPublishing();
}
/**
* Configure the package policies.
*/
protected function configurePolicies()
protected function registerFacade()
{
$this->app->singleton('filament', Filament::class);
}
protected function registerLivewireComponents(): void
{
$this->app->afterResolving(BladeCompiler::class, function () {
$prefix = config('filament.prefix.component', '');
/** @var LivewireComponent $component */
foreach (config('filament.livewire', []) as $alias => $component) {
$alias = $prefix ? "$prefix-$alias" : $alias;
Livewire::component($alias, $component);
}
});
}
protected function bootPolicies(): void
{
Gate::guessPolicyNamesUsing(function ($modelClass) {
return 'Filament\\Policies\\'.class_basename($modelClass).'Policy';
});
}
/**
* Configure the Filament Blade components.
*
* @return void
*/
protected function configureComponents()
protected function bootResources(): void
{
$components = collect((new Filesystem)->allFiles(__DIR__.'/View/Components'))->map(function (SplFileInfo $file) {
$baseName = class_basename(str_replace('.php', '', $file->getPathname()));
return "\\Filament\\View\\Components\\{$baseName}";
})->all();
$this->loadViewComponentsAs('filament', $components);
$this->loadViewsFrom(__DIR__.'/../resources/views', 'filament');
$this->loadViewComponentsAs(config('filament.prefix.component', 'filament'), config('filament.components', []));
}
/**
* Configure the Filament Livewire components.
*
* @return void
*/
protected function configureLivewireComponents()
protected function bootDirectives(): void
{
collect((new Filesystem)->allFiles(__DIR__.'/Http/Livewire'))->map(function (SplFileInfo $file) {
$baseName = class_basename(str_replace('.php', '', $file->getPathname()));
Livewire::component('filament::'.Str::of($baseName)->kebab(), "\\Filament\\Http\\Livewire\\{$baseName}");
});
Blade::directive('filamentStyles', [BladeDirectives::class, 'styles']);
Blade::directive('filamentScripts', [BladeDirectives::class, 'scripts']);
}
/**
* Configure publishing for the package.
*
* @return void
*/
protected function configurePublishing()
protected function bootPublishing(): void
{
if (! $this->app->runningInConsole()) {
return;
@@ -100,37 +83,30 @@ class FilamentServiceProvider extends ServiceProvider
], 'filament-views');
$this->publishes([
// __DIR__.'/../database/migrations/2020_09_13_200000_create_resources_table.php' => database_path('migrations/2020_09_13_200000_create_resources_table.php'),
], 'filament-resources-migrations');
$this->publishes([
$this->getRoutes() => base_path('routes/filament.php'),
], 'filament-routes');
__DIR__.'/../dist' => public_path('vendor/filament'),
], 'filament-assets');
}
/**
* Configure the routes offered by the application.
*
* @return void
*/
protected function configureRoutes()
protected function bootRoutes(): void
{
if (Filament::$registersRoutes) {
Route::group([
'namespace' => 'Filament\Http\Controllers',
], function () {
$this->loadRoutesFrom($this->getRoutes());
});
$this->loadRoutesFrom($this->getRoutes());
}
}
/**
* Get the routes for the application.
*
* @return string
*/
protected function getRoutes()
protected function bootCommands(): void
{
return __DIR__.'/../routes/'.config('filament.stack').'.php';
if (!$this->app->runningInConsole()) {
return;
}
$this->commands([
//...
]);
}
}
protected function getRoutes(): string
{
return __DIR__.'/../routes/filament.php';
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Filament\Http\Controllers;
use Filament\Traits\CanPretendToBeAFile;
class AssetController
{
use CanPretendToBeAFile;
public function css()
{
return $this->pretendResponseIsFile('css/filament.css', 'text/css; charset=utf-8');
}
public function cssMap()
{
return $this->pretendResponseIsFile('css/filament.css.map', 'application/javascript; charset=utf-8');
}
public function js()
{
return $this->pretendResponseIsFile('js/filament.js', 'application/javascript; charset=utf-8');
}
public function jsMap()
{
return $this->pretendResponseIsFile('js/filament.js.map', 'application/javascript; charset=utf-8');
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Filament\Http\Livewire\Auth;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class Login extends Component
{
public $email;
public $password;
public function login()
{
$data = $this->validate([
'email' => 'required|email',
'password' => 'required|min:8',
]);
if (Auth::attempt($data)) {
return redirect()->intended(RouteServiceProvider::HOME);
}
$this->addError('password', trans('auth.failed'));
}
public function render()
{
return view('filament::livewire.auth.login')->layout('filament::layouts.app');
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace Filament\Traits;
use Filament;
trait CanPretendToBeAFile
{
protected function pretendResponseIsFile($file, $contentType)
{
$path = Filament::distPath($file);
if (!file_exists($path)) {
abort(404);
}
$expires = strtotime('+1 year');
$lastModified = filemtime($path);
$cacheControl = 'public, max-age=31536000';
if ($this->matchesCache($lastModified)) {
return response()->noContent(304, [
'Expires' => $this->httpDate($expires),
'Cache-Control' => $cacheControl,
]);
}
return response()->file($path, [
'Content-Type' => $contentType,
'Expires' => $this->httpDate($expires),
'Cache-Control' => $cacheControl,
'Last-Modified' => $this->httpDate($lastModified),
]);
}
protected function matchesCache($lastModified)
{
$ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? '';
return @strtotime($ifModifiedSince) === $lastModified;
}
protected function httpDate($timestamp)
{
return sprintf('%s GMT', gmdate('D, d M Y H:i:s', $timestamp));
}
}
@@ -1,23 +0,0 @@
<?php
namespace Filament\View\Components;
use Illuminate\View\Component;
use Filament\Filament;
class DropdownUserManagement extends Component
{
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\View\View|\Closure|string|null
*/
public function render()
{
if (! Filament::hasUserManagementFeatures()) {
return;
}
return view('filament::components.dropdown-user-management');
}
}
+12
View File
@@ -0,0 +1,12 @@
module.exports = {
future: {
removeDeprecatedGapUtilities: true,
purgeLayersByDefault: true,
},
purge: ['./resources/views/**/*.php', './resources/js/**/*.js'],
theme: {
extend: {},
},
variants: {},
plugins: [],
}
+80
View File
@@ -0,0 +1,80 @@
require('dotenv').config()
let mix = require('laravel-mix')
/*
|--------------------------------------------------------------------------
| Config
|--------------------------------------------------------------------------
|
*/
const SRC = 'resources'
const DIST = 'dist'
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your application.
|
*/
// set paths
mix.setPublicPath(DIST)
mix.setResourceRoot(`/${SRC}/`)
/**
* Process Javascript
*
* https://laravel.com/docs/master/mix#working-with-scripts
*/
mix.js(`${SRC}/js/filament.js`, 'js')
/**
* Process CSS via PostCSS
*
*
* https://laravel.com/docs/master/mix#postcss
*/
mix.postCss(`${SRC}/css/filament.css`, 'css', [
require('postcss-import'),
require('tailwindcss'),
require('postcss-nested'),
])
/**
* Sourcemaps
*
* Provide extra debugging information to your browser's
* developer tools when using compiled assets.
*
* https://laravel.com/docs/master/mix#css-source-maps
*/
mix.sourceMaps()
if (mix.inProduction()) {
/**
* Versioning / Cache Busting
*
* After generating the versioned file, you won't know the exact file name.
* So, you should use Laravel's global mix function within your views
* to load the appropriately hashed asset.
*
* https://laravel.com/docs/master/mix#versioning-and-cache-busting
*/
mix.version()
}
/**
* BrowserSync
*
* Automatically monitor your files for changes,
* and inject your changes into the browser without requiring a manual refresh
*
* https://laravel.com/docs/master/mix#browsersync-reloading
*/
mix.browserSync({
proxy: process.env.BROWSERSYNC_PROXY || 'http://127.0.0.1:8000',
https: process.env.BROWSERSYNC_HTTPS || false,
})