mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
REboot
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# BrowserSync
|
||||
# BROWSERSYNC_PROXY='http://127.0.0.1:8000'
|
||||
# BROWSERSYNC_HTTPS=false
|
||||
+6
-3
@@ -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
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
Vendored
+2
@@ -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*/
|
||||
Vendored
+1
@@ -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":""}
|
||||
Vendored
+2
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+6
@@ -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"
|
||||
}
|
||||
Generated
+14574
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@import 'tailwindcss/base';
|
||||
@import './base.css';
|
||||
|
||||
@import 'tailwindcss/components';
|
||||
/* @import './components/button.css'; */
|
||||
|
||||
@import 'tailwindcss/utilities';
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1 @@
|
||||
<div>login form...</div>
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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()) {
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -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
@@ -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
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Filament;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class FilamentFacade extends Facade
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return Filament::class;
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
future: {
|
||||
removeDeprecatedGapUtilities: true,
|
||||
purgeLayersByDefault: true,
|
||||
},
|
||||
purge: ['./resources/views/**/*.php', './resources/js/**/*.js'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {},
|
||||
plugins: [],
|
||||
}
|
||||
@@ -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,
|
||||
})
|
||||
Reference in New Issue
Block a user