Install Filament

This commit is contained in:
Dan Harrin
2023-02-16 13:14:19 +00:00
parent 91a13359ac
commit cc57700497
31 changed files with 529 additions and 39 deletions
@@ -0,0 +1,56 @@
<?php
namespace App\Providers\Filament;
use Filament\Context;
use Filament\ContextProvider;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Http\Middleware\MirrorConfigToSubpackages;
use Filament\Pages;
use Filament\Support\Color;
use Filament\Widgets;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
class AdminContextProvider extends ContextProvider
{
public function context(Context $context): Context
{
return $context
->default()
->id('admin')
->path('admin')
->login()
->primaryColor(Color::Amber)
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
->pages([
Pages\Dashboard::class,
])
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
->widgets([
Widgets\AccountWidget::class,
Widgets\FilamentInfoWidget::class,
])
->middleware([
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
AuthenticateSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
DispatchServingFilamentEvent::class,
MirrorConfigToSubpackages::class,
])
->authMiddleware([
Authenticate::class,
]);
}
}
+6 -2
View File
@@ -2,7 +2,10 @@
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require": {
"php": "^8.1",
@@ -39,7 +42,8 @@
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
"@php artisan filament:upgrade"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
+1
View File
@@ -193,6 +193,7 @@ return [
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\Filament\AdminContextProvider::class,
App\Providers\RouteServiceProvider::class,
],
+5 -1
View File
@@ -5,8 +5,12 @@
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"@tailwindcss/forms": "^0.5.2",
"@tailwindcss/typography": "^0.5.4",
"autoprefixer": "^10.4.7",
"laravel-vite-plugin": "^0.7.2",
"postcss": "^8.4.14",
"tailwindcss": "^3.1",
"vite": "^4.0.0"
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
function keyValueFormComponent({state}){return{state,rows:[],shouldUpdateRows:!0,init:function(){this.updateRows(),this.rows.length<=0&&this.addRow(),this.shouldUpdateRows=!0,this.$watch("state",()=>{if(!this.shouldUpdateRows){this.shouldUpdateRows=!0;return}this.updateRows()})},addRow:function(){this.rows.push({key:"",value:""}),this.updateState()},deleteRow:function(index){this.rows.splice(index,1),this.rows.length<=0&&this.addRow(),this.updateState(),this.shouldUpdateRows=!0},reorderRows:function(event){let rows=Alpine.raw(this.rows),reorderedRow=rows.splice(event.oldIndex,1)[0];rows.splice(event.newIndex,0,reorderedRow),this.rows=rows,this.updateState()},updateRows:function(){let rows=[];for(let[key,value]of Object.entries(this.state??{}))rows.push({key,value});this.rows=rows},updateState:function(){let state2={};this.rows.forEach(row=>{row.key===""||row.key===null||(state2[row.key]=row.value)}),this.shouldUpdateRows=!1,this.state=state2}}}export{keyValueFormComponent as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
function tagsInputFormComponent({state}){return{newTag:"",state,createTag:function(){if(this.newTag=this.newTag.trim(),this.newTag!==""){if(this.state.includes(this.newTag)){this.newTag="";return}this.state.push(this.newTag),this.newTag=""}},deleteTag:function(tagToDelete){this.state=this.state.filter(tag=>tag!==tagToDelete)}}}export{tagsInputFormComponent as default};
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
function textareaFormComponent(){return{init:function(){this.$nextTick(()=>{this.render()})},render:function(){this.$el.scrollHeight>0&&(this.$el.style.height="150px",this.$el.style.height=this.$el.scrollHeight+2+"px")}}}export{textareaFormComponent as default};
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
var u=t=>new Promise(e=>{window.addEventListener("async-alpine:load",s=>{s.detail.id===t.id&&e()})}),a=u,_=()=>new Promise(t=>{"requestIdleCallback"in window?window.requestIdleCallback(t):setTimeout(t,200)}),l=_,c=t=>new Promise(e=>{let s=t.indexOf("("),i=t.slice(s),n=window.matchMedia(i);n.matches?e():n.addEventListener("change",e,{once:!0})}),d=c,f=(t,e)=>new Promise(s=>{let i="0px 0px 0px 0px";if(e.indexOf("(")!==-1){let o=e.indexOf("(")+1;i=e.slice(o,-1)}let n=new IntersectionObserver(o=>{o[0].isIntersecting&&(n.disconnect(),s())},{rootMargin:i});n.observe(t.el)}),p=f,h="__internal_",r={Alpine:null,_options:{prefix:"ax-",alpinePrefix:"x-",root:"load",inline:"load-src",defaultStrategy:"immediate"},_alias:!1,_data:{},_realIndex:0,get _index(){return this._realIndex++},init(t,e={}){return this.Alpine=t,this._options={...this._options,...e},this},start(){return this._processInline(),this._setupComponents(),this._mutations(),this},data(t,e=!1){return this._data[t]={loaded:!1,download:e},this},url(t,e){!t||!e||(this._data[t]||this.data(t),this._data[t].download=()=>import(this._parseUrl(e)))},alias(t){this._alias=t},_processInline(){let t=document.querySelectorAll(`[${this._options.prefix}${this._options.inline}]`);for(let e of t)this._inlineElement(e)},_inlineElement(t){let e=t.getAttribute(`${this._options.alpinePrefix}data`),s=t.getAttribute(`${this._options.prefix}${this._options.inline}`);if(!e||!s)return;let i=this._parseName(e);this.url(i,s)},_setupComponents(){let t=document.querySelectorAll(`[${this._options.prefix}${this._options.root}]`);for(let e of t)this._setupComponent(e)},_setupComponent(t){let e=t.getAttribute(`${this._options.alpinePrefix}data`);t.setAttribute(`${this._options.alpinePrefix}ignore`,"");let s=this._parseName(e),i=t.getAttribute(`${this._options.prefix}${this._options.root}`)||this._options.defaultStrategy;this._componentStrategy({name:s,strategy:i,el:t,id:t.id||this._index})},async _componentStrategy(t){let e=t.strategy.split("|").map(i=>i.trim()).filter(i=>i!=="immediate").filter(i=>i!=="eager");if(!e.length){await this._download(t.name),this._activate(t);return}let s=[];for(let i of e){if(i==="idle"){s.push(l());continue}if(i.startsWith("visible")){s.push(p(t,i));continue}if(i.startsWith("media")){s.push(d(i));continue}i==="event"&&s.push(a(t))}Promise.all(s).then(async()=>{await this._download(t.name),this._activate(t)})},async _download(t){if(t.startsWith(h)||(this._handleAlias(t),!this._data[t]||this._data[t].loaded))return;let e=await this._getModule(t);this.Alpine.data(t,e),this._data[t].loaded=!0},async _getModule(t){if(!this._data[t])return;let e=await this._data[t].download();return typeof e=="function"?e:e[t]||e.default||Object.values(e)[0]||!1},_activate(t){t.el.removeAttribute(`${this._options.alpinePrefix}ignore`),t.el._x_ignore=!1,this.Alpine.initTree(t.el)},_mutations(){new MutationObserver(e=>{for(let s of e)if(s.addedNodes)for(let i of s.addedNodes)i.nodeType===1&&(i.hasAttribute(`${this._options.prefix}${this._options.root}`)&&this._mutationEl(i),i.querySelectorAll(`[${this._options.prefix}${this._options.root}]`).forEach(o=>this._mutationEl(o)))}).observe(document,{attributes:!0,childList:!0,subtree:!0})},_mutationEl(t){t.hasAttribute(`${this._options.prefix}${this._options.inline}`)&&this._inlineElement(t),this._setupComponent(t)},_handleAlias(t){!this._alias||this._data[t]||this.url(t,this._alias.replace("[name]",t))},_parseName(t){return(t||"").split(/[({]/g)[0]||`${h}${this._index}`},_parseUrl(t){return new RegExp("^(?:[a-z+]+:)?//","i").test(t)?t:new URL(t,document.baseURI).href}};document.addEventListener("alpine:init",()=>{window.AsyncAlpine=r,r.init(Alpine,window.AsyncAlpineOptions||{}),document.dispatchEvent(new CustomEvent("async-alpine:init")),r.start()});
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
(()=>{function src_default(Alpine){Alpine.directive("collapse",collapse),collapse.inline=(el,{modifiers})=>{!modifiers.includes("min")||(el._x_doShow=()=>{},el._x_doHide=()=>{})};function collapse(el,{modifiers}){let duration=modifierValue(modifiers,"duration",250)/1e3,floor=modifierValue(modifiers,"min",0),fullyHide=!modifiers.includes("min");el._x_isShown||(el.style.height=`${floor}px`),!el._x_isShown&&fullyHide&&(el.hidden=!0),el._x_isShown||(el.style.overflow="hidden");let setFunction=(el2,styles)=>{let revertFunction=Alpine.setStyles(el2,styles);return styles.height?()=>{}:revertFunction},transitionStyles={transitionProperty:"height",transitionDuration:`${duration}s`,transitionTimingFunction:"cubic-bezier(0.4, 0.0, 0.2, 1)"};el._x_transition={in(before=()=>{},after=()=>{}){fullyHide&&(el.hidden=!1),fullyHide&&(el.style.display=null);let current=el.getBoundingClientRect().height;el.style.height="auto";let full=el.getBoundingClientRect().height;current===full&&(current=floor),Alpine.transition(el,Alpine.setStyles,{during:transitionStyles,start:{height:current+"px"},end:{height:full+"px"}},()=>el._x_isShown=!0,()=>{el.getBoundingClientRect().height==full&&(el.style.overflow=null)})},out(before=()=>{},after=()=>{}){let full=el.getBoundingClientRect().height;Alpine.transition(el,setFunction,{during:transitionStyles,start:{height:full+"px"},end:{height:floor+"px"}},()=>el.style.overflow="hidden",()=>{el._x_isShown=!1,el.style.height==`${floor}px`&&fullyHide&&(el.style.display="none",el.hidden=!0)})}}}}function modifierValue(modifiers,key,fallback){if(modifiers.indexOf(key)===-1)return fallback;let rawValue=modifiers[modifiers.indexOf(key)+1];if(!rawValue)return fallback;if(key==="duration"){let match=rawValue.match(/([0-9]+)ms/);if(match)return match[1]}if(key==="min"){let match=rawValue.match(/([0-9]+)px/);if(match)return match[1]}return rawValue}var module_default=src_default;document.addEventListener("alpine:init",()=>{window.Alpine.plugin(module_default)});})();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5
View File
@@ -0,0 +1,5 @@
@import '../../vendor/filament/forms/dist/index.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
-1
View File
@@ -1 +0,0 @@
import './bootstrap'
-32
View File
@@ -1,32 +0,0 @@
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
import axios from 'axios'
window.axios = axios
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
// import Echo from 'laravel-echo';
// import Pusher from 'pusher-js';
// window.Pusher = Pusher;
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: import.meta.env.VITE_PUSHER_APP_KEY,
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
// enabledTransports: ['ws', 'wss'],
// });
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="application-name" content="{{ config('app.name') }}">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ config('app.name') }}</title>
<style>[x-cloak] { display: none !important; }</style>
@livewireStyles
@filamentStyles
@vite('resources/css/app.css')
</head>
<body class="antialiased">
{{ $slot }}
@livewire('notifications')
@livewireScripts
@filamentScripts
@vite('resources/js/app.js')
<script src="//unpkg.com/alpinejs" defer></script>
</body>
</html>
+21
View File
@@ -0,0 +1,21 @@
const colors = require('tailwindcss/colors')
module.exports = {
content: ['./resources/**/*.blade.php', './vendor/filament/**/*.blade.php'],
darkMode: 'class',
theme: {
extend: {
colors: {
danger: colors.rose,
primary: colors.blue,
secondary: colors.gray,
success: colors.green,
warning: colors.yellow,
},
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
],
}
+7 -2
View File
@@ -1,11 +1,16 @@
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'
import laravel, { refreshPaths } from 'laravel-vite-plugin'
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
refresh: [
...refreshPaths,
'app/Http/Livewire/**',
'app/Forms/Components/**',
'app/Tables/Columns/**',
],
}),
],
})
+1 -1
View File
@@ -11,7 +11,7 @@ for (const [file, options] of Object.entries(schema)) {
fs.mkdirSync(`images/${directory}`, { recursive: true })
}
;(async () => {
(async () => {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(`http://localhost:8000/${options.url}`, {