Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenjude committed Feb 29, 2024
1 parent 684a4ba commit d2f1694
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 87 deletions.
8 changes: 8 additions & 0 deletions config/jetstream.php → config/filament-jetstream.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
// config for FilamentJetstream/FilamentJetstream
return [

/*
* Disable Jetstream and Fortify routes. If you want your users to still used
*/
'enable_route' => [
'fortify' => true,
'jetstream' => false,
],

'navigation_items' => [
'profile' => [
'display' => false,
Expand Down
21 changes: 21 additions & 0 deletions routes/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

use Filament\Facades\Filament;
use Illuminate\Support\Facades\Route;

$panel = Filament::getCurrentPanel();

Route::redirect('/login', "/{$panel?->getPath()}/login")->name('login');

Route::redirect('/register', "/{$panel?->getPath()}/register")->name('register');

Route::get('/team-invitations/{invitation}', [\Laravel\Jetstream\Http\Controllers\TeamInvitationController::class, 'accept'])
->middleware([
'signed',
'verified',
'auth:'.$panel->getAuthGuard(),
\Illuminate\Session\Middleware\AuthenticateSession::class
])
->name('team-invitations.accept');

Route::redirect('/dashboard', "/{$panel?->getPath()}")->name('dashboard');
221 changes: 168 additions & 53 deletions src/Commands/FilamentJetstreamCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,60 @@

namespace FilamentJetstream\FilamentJetstream\Commands;

use Filament\Facades\Filament;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Process\Process;

class FilamentJetstreamCommand extends Command
{
public $signature = 'filament:jetstream:install {--teams : Indicates if team support should be installed}
{--api : Indicates if API support should be installed}
{--verification : Indicates if email verification support should be installed}
{--dark : Indicate that dark mode support should be installed}';
{--api : Indicates if API support should be installed}';

public $description = 'Install the Jetstream component and it\'s filament component';
public $description = 'Install the Jetstream and filament components.';

public function handle(): int
{
$this->callSilently('jetstream:install', [
$this->info('Filament Jetstream scaffolding...');

$this->call('jetstream:install', [
'stack' => 'livewire',
'--verification' => true,
'--dark' => true,
'--teams' => $this->option('teams'),
'--api' => $this->option('api'),
'--verification' => $this->option('verification'),
'--dark' => $this->option('dark'),
'--api' => $this->option('api')
]);

$this->configureUser();

$this->configureEmailVerification();

if ($this->option('teams')) {
$this->configureTeam();
}

$this->configureRoute();

$this->configurePanel();

$this->configureAssets();

$this->line('');

$this->info('Jetstream scaffolding installed successfully.');
$this->info('Filament Jetstream scaffolding installed successfully.');

return self::SUCCESS;
}

public function configureUser(): void
protected function configureUser(): void
{
$this->replaceInFile(
search: 'use Laravel\Sanctum\HasApiTokens;',
replace: 'use Filament\Panel;'.PHP_EOL.
'use Filament\Models\Contracts\FilamentUser;'.PHP_EOL.
'use Laravel\Sanctum\HasApiTokens;'.PHP_EOL,
replace: <<<'HEREDOC'
use Filament\Panel;
use Filament\Models\Contracts\FilamentUser;
use Laravel\Sanctum\HasApiTokens;
HEREDOC,
path: app_path('Models/User.php'),
);

Expand All @@ -55,29 +66,44 @@ public function configureUser(): void
);

$this->replaceInFile(
search: '}'.PHP_EOL,
replace: 'public function canAccessPanel(Panel $panel): bool'.PHP_EOL.'{'.PHP_EOL.
' return;'.PHP_EOL.'}'.PHP_EOL.'}'.PHP_EOL,
search: '}',
replace: <<<'HEREDOC'
public function canAccessPanel(Panel $panel): bool
{
return true;
}
}
HEREDOC,
path: app_path('Models/User.php'),
);
}

if ($this->option('verification')) {
$this->replaceInFile(
search: 'implements ',
replace: 'implements MustVerifyEmail, ',
path: app_path('Models/User.php'),
);
}
protected function configureEmailVerification(): void
{
$this->replaceInFile(
search: '// use Illuminate\Contracts\Auth\MustVerifyEmail;',
replace: 'use Illuminate\Contracts\Auth\MustVerifyEmail;',
path: app_path('Models/User.php'),
);

$this->replaceInFile(
search: 'implements ',
replace: 'implements MustVerifyEmail, ',
path: app_path('Models/User.php'),
);
}

public function configureTeam(): void
protected function configureTeam(): void
{
$this->replaceInFile(
search: 'use Laravel\Sanctum\HasApiTokens;',
replace: 'use Illuminate\Support\Collection;'.PHP_EOL.
'use Illuminate\Database\Eloquent\Model;'.PHP_EOL.
'use Filament\Models\Contracts\HasTenants;'.PHP_EOL.
'use Laravel\Sanctum\HasApiTokens;'.PHP_EOL,
replace: <<<'HEREDOC'
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Model;
use Filament\Models\Contracts\HasTenants;
use Laravel\Sanctum\HasApiTokens;
HEREDOC,
path: app_path('Models/User.php'),
);

Expand All @@ -88,54 +114,143 @@ public function configureTeam(): void
);

$this->replaceInFile(
search: '}'.PHP_EOL.'}'.PHP_EOL,
replace: 'public function canAccessTenant(Model $tenant): bool'.PHP_EOL.'{'.PHP_EOL.
' return $this->belongsToTeam($tenant);'.PHP_EOL.'}'.PHP_EOL.'}'.PHP_EOL,
search: <<<'HEREDOC'
}
}
HEREDOC,
replace: <<<'HEREDOC'
}
public function getTenants(Panel $panel): Collection
{
return $this->allTeams();
}
public function canAccessTenant(Model $tenant): bool
{
return $this->belongsToTeam($tenant);
}
}
HEREDOC,
path: app_path('Models/User.php'),
);
}

protected function configureRoute()
{
$this->replaceInFile(
search: '}'.PHP_EOL.'}'.PHP_EOL,
replace: 'public function getTenants(Panel $panel): Collection'.PHP_EOL.'{'.PHP_EOL.
' return $this->allTeams();'.PHP_EOL.'}'.PHP_EOL.'}'.PHP_EOL,
path: app_path('Models/User.php'),
search: <<<'HEREDOC'
Route::middleware([
'auth:sanctum',
config('jetstream.auth_session'),
'verified',
])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
HEREDOC,
replace: '',
path: base_path('routes/web.php')
);
}

protected function configurePanel()
{
if (!empty(Filament::getPanels())) {
(new Filesystem)->deleteDirectory(app_path('Providers/Filament'));
}

$this->callSilently('make:filament-panel', ['id' => 'app', '--force' => true]);

$this->replaceInFile(
search: '->login()',
replace: <<<'HEREDOC'
->default()
->plugin(
\FilamentJetstream\FilamentJetstream\FilamentJetstreamPlugin::make()
);
HEREDOC,
path: app_path('Providers/Filament/AppPanelProvider.php')
);
}

public function configureAssets(): void

protected function configureAssets(): void
{
$this->replaceInFile(
search: 'content: ['.PHP_EOL,
replace: 'content: ['.PHP_EOL.
'./app/Filament/**/*.php'.PHP_EOL.
'./resources/views/filament/**/*.blade.php'.PHP_EOL.
'./vendor/filament/**/*.blade.php'.PHP_EOL,
path: base_path('Models/User.php'),
search: file_get_contents(base_path('tailwind.config.js')),
replace: <<<'HEREDOC'
import preset from './vendor/filament/filament/tailwind.config.preset';
export default {
presets: [preset],
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./vendor/laravel/jetstream/**/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
'./app/Filament/**/*.php',
'./resources/views/filament/**/*.blade.php',
'./vendor/filament/**/*.blade.php',
],
};
HEREDOC,
path: base_path('tailwind.config.js'),
);

$this->replaceInFile(
search: 'implements FilamentUser',
replace: 'implements FilamentUser, HasTenants',
path: app_path('Models/User.php'),
search: 'indigo',
replace: 'gray',
path: resource_path('views/components/checkbox.blade.php'),
);

$this->replaceInFile(
search: '}'.PHP_EOL.'}'.PHP_EOL,
replace: 'public function canAccessTenant(Model $tenant): bool'.PHP_EOL.'{'.PHP_EOL.
' return $this->belongsToTeam($tenant);'.PHP_EOL.'}'.PHP_EOL.'}'.PHP_EOL,
path: app_path('Models/User.php'),
search: 'indigo',
replace: 'gray',
path: resource_path('views/components/button.blade.php'),
);

$this->replaceInFile(
search: '}'.PHP_EOL.'}'.PHP_EOL,
replace: 'public function getTenants(Panel $panel): Collection'.PHP_EOL.'{'.PHP_EOL.
' return $this->allTeams();'.PHP_EOL.'}'.PHP_EOL.'}'.PHP_EOL,
path: app_path('tailwind.config.js'),
search: 'indigo',
replace: 'gray',
path: resource_path('views/components/input.blade.php'),
);

$this->replaceInFile(
search: 'indigo',
replace: 'gray',
path: resource_path('views/components/secondary-button.blade.php'),
);

if (file_exists(base_path('pnpm-lock.yaml'))) {
$this->runCommands(['pnpm install', 'pnpm run build']);
} elseif (file_exists(base_path('yarn.lock'))) {
$this->runCommands(['yarn install', 'yarn run build']);
} else {
$this->runCommands(['npm install', 'npm run build']);
}
}

protected function replaceInFile($search, $replace, $path)
{
file_put_contents($path, str_replace($search, $replace, file_get_contents($path)));
}

protected function runCommands($commands)
{
$process = Process::fromShellCommandline(implode(' && ', $commands), null, null, null, null);

if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) {
try {
$process->setTty(true);
} catch (RuntimeException $e) {
$this->output->writeln(' <bg=yellow;fg=black> WARN </> '.$e->getMessage().PHP_EOL);
}
}

$process->run(function ($type, $line) {
$this->output->write(' '.$line);
});
}
}
Loading

0 comments on commit d2f1694

Please sign in to comment.