changeset 25:1a717c7b211f codex

added support for some basic views
author Luka Sitas <sitas.luka.97@gmail.com>
date Sun, 11 May 2025 21:03:51 -0400
parents 31109c61ce02
children 555bfaa500ac
files src/Generator/Controller/stubs/controller.stub src/Generator/Generator.php src/Generator/View/CreateEditViewGenerator.php src/Generator/View/IndexViewGenerator.php src/Generator/View/ShowViewGenerator.php src/Generator/View/ViewGenerator.php src/Generator/View/stubs/create_edit.stub src/Generator/View/stubs/index.stub src/Generator/View/stubs/show.stub src/MagicForgerServiceProvider.php src/Replacer/Replacer.php
diffstat 11 files changed, 533 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/Generator/Controller/stubs/controller.stub	Tue Apr 22 21:37:44 2025 -0400
+++ b/src/Generator/Controller/stubs/controller.stub	Sun May 11 21:03:51 2025 -0400
@@ -17,6 +17,7 @@
     {
         $data = [];
         $data['items'] = {{ model }}::all();
+				$data['fields'] = (new {{ model }}()->getFillable());
 
         return view('{{ tableName }}.index', $data);
     }
@@ -29,6 +30,7 @@
     public function create()
     {
         $data = [];
+				$data['fields'] = (new {{ model }}()->getFillable());
 
         return view('{{ tableName }}.create_edit', $data);
     }
@@ -58,6 +60,7 @@
     {
         $data = [];
         $data['item'] = ${{ modelVariable }};
+				$data['fields'] = (new {{ model }}()->getFillable());
 
         return view('{{ tableName }}.show', $data);
     }
@@ -72,6 +75,7 @@
     {
         $data = [];
         $data['item'] = ${{ modelVariable }};
+				$data['fields'] = (new {{ model }}()->getFillable());
 
         // Load data for relationships
 
--- a/src/Generator/Generator.php	Tue Apr 22 21:37:44 2025 -0400
+++ b/src/Generator/Generator.php	Sun May 11 21:03:51 2025 -0400
@@ -47,6 +47,7 @@
             $this->input->setOption('controller', true);
             $this->input->setOption('model', true);
             $this->input->setOption('request', true);
+            $this->input->setOption('view', true);
             $this->input->setOption('route', true);
         }
 
@@ -74,6 +75,10 @@
             $this->createRequest();
         }
 
+        if ($this->option('view')) {
+            $this->createView();
+        }
+
         if ($this->option('route')) {
             $this->createRoute();
         }
@@ -89,6 +94,7 @@
             ['controller', 'c', InputOption::VALUE_NONE, 'Generate a controller class for the table.'],
             ['model', 'm', InputOption::VALUE_NONE, 'Generate a model class for the table.'],
             ['request', 'r', InputOption::VALUE_NONE, 'Generate base request classes for the table.'],
+            ['view', '', InputOption::VALUE_NONE, 'Generate base views for the table.'],
             ['route', 'w', InputOption::VALUE_NONE, 'Generate base routes classes for the table.'],
         ]);
     }
@@ -115,6 +121,11 @@
         $this->call('mf:request', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh'), '--all' => true]);
     }
 
+    protected function createView()
+    {
+        $this->call('mf:view', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh'), '--all' => true]);
+    }
+
     protected function createRoute()
     {
         $this->call('mf:route', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/CreateEditViewGenerator.php	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:create_edit_view')]
+class CreateEditViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:create_edit_view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the CreateEditView File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'CreateEditView';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/create_edit.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->create_edit_view_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['Resources\\', '\\'], ['resources/', '/'], $this->getViewNamespace($this->getTableInput()).'create_edit.blade.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/IndexViewGenerator.php	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:index_view')]
+class IndexViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:index_view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the IndexView File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'IndexView';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/index.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->index_view_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['Resources\\', '\\'], ['resources/', '/'], $this->getViewNamespace($this->getTableInput()).'index.blade.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/ShowViewGenerator.php	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:show_view')]
+class ShowViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:show_view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the ShowView File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'ShowView';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/show.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->show_view_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['Resources\\', '\\'], ['resources/', '/'], $this->getViewNamespace($this->getTableInput()).'show.blade.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/ViewGenerator.php	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,105 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:view')]
+class ViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the View File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'View';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        // First we need to ensure that the table exists, then we can
+        if (! $this->tableExists($this->getTableInput())) {
+            $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
+
+            return false;
+        }
+
+        if ($this->option('all')) {
+            $this->input->setOption('index_view', true);
+            $this->input->setOption('create_edit_view', true);
+            $this->input->setOption('show_view', true);
+        }
+
+        if ($this->option('index_view')) {
+            $this->createIndexView();
+        }
+
+        if ($this->option('create_edit_view')) {
+            $this->createCreateEditView();
+        }
+
+        if ($this->option('show_view')) {
+            $this->createShowView();
+        }
+    }
+
+    /**
+     * Get the console command options.
+     */
+    protected function getOptions(): array
+    {
+        return array_merge(parent::getOptions(), [
+            ['all', 'a', InputOption::VALUE_NONE, 'Generate all views for the table.'],
+            ['index_view', 'i', InputOption::VALUE_NONE, 'Generate index view for the table.'],
+            ['create_edit_view', 'c', InputOption::VALUE_NONE, 'Generate create_edit view for the table.'],
+            ['show_view', 's', InputOption::VALUE_NONE, 'Generate show view for the table.'],
+        ]);
+    }
+
+    /**
+     * Interact further with the user if they were prompted for missing arguments.
+     */
+    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void {}
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub() {}
+
+    protected function createIndexView()
+    {
+        $this->call('mf:index_view', ['table' => $this->getTableInput()]);
+    }
+
+    protected function createCreateEditView()
+    {
+        $this->call('mf:create_edit_view', ['table' => $this->getTableInput()]);
+    }
+
+    protected function createShowView()
+    {
+        $this->call('mf:show_view', ['table' => $this->getTableInput()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/stubs/create_edit.stub	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,39 @@
+<x-app-layout>
+    <x-slot name="header">
+        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
+            {{ isset($item) ? 'Edit' : 'Create' }} {{ ucfirst('{{ modelVariable }}') }}
+        </h2>
+    </x-slot>
+
+    <div class="py-12">
+        <div class="max-w-2xl mx-auto sm:px-6 lg:px-8">
+            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg p-6">
+                <form method="POST" action="{{ isset($item) ? route('{{ tableName }}.update', $item) : route('{{ tableName }}.store') }}">
+                    @csrf
+                    @if(isset($item))
+                        @method('PUT')
+                    @endif
+
+                    @foreach($fields as $field)
+                        <div class="mb-4">
+                            <label for="{{ $field }}" class="block text-gray-700">{{ ucfirst($field) }}</label>
+                            <input type="text" name="{{ $field }}" id="{{ $field }}"
+                                   class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring focus:ring-blue-200"
+                                   value="{{ old('$field', isset($item) ? $item->$field : '') }}">
+                            @error($field)
+                                <span class="text-red-600 text-sm">{{ $message }}</span>
+                            @enderror
+                        </div>
+                    @endforeach
+
+                    <div class="flex justify-end">
+                        <a href="{{ route('{{ tableName }}.index') }}" class="mr-2 px-4 py-2 bg-gray-200 rounded hover:bg-gray-300">Back</a>
+                        <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
+                            {{ isset($item) ? 'Update' : 'Create' }}
+                        </button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</x-app-layout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/stubs/index.stub	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,52 @@
+<x-app-layout>
+    <x-slot name="header">
+        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
+            All {{ Str::plural(ucfirst('{{ modelVariable }}')) }}
+        </h2>
+    </x-slot>
+
+    <div class="py-12">
+        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
+            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg p-6">
+                <div class="flex items-center justify-between mb-4">
+                    <span></span>
+                    <a href="{{ route('{{ tableName }}.create') }}" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
+                        + New {{ ucfirst('{{ modelVariable }}') }}
+                    </a>
+                </div>
+                <table class="w-full text-left border-collapse">
+                    <thead>
+                        <tr>
+                            @foreach($fields as $field)
+                                <th class="border-b p-2">{{ ucfirst($field) }}</th>
+                            @endforeach
+                            <th class="border-b p-2">Actions</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        @forelse ($items as $item)
+                            <tr>
+                                @foreach($fields as $field)
+                                    <td class="border-b p-2">{{ $item->$field }}</td>
+                                @endforeach
+                                <td class="border-b p-2 flex space-x-2">
+                                    <a href="{{ route('{{ tableName }}.show', $item) }}" class="text-blue-600 hover:underline">View</a>
+                                    <a href="{{ route('{{ tableName }}.edit', $item) }}" class="text-yellow-600 hover:underline">Edit</a>
+                                    <form action="{{ route('{{ tableName }}.destroy', $item) }}" method="POST" class="inline">
+                                        @csrf
+                                        @method('DELETE')
+                                        <button type="submit" class="text-red-600 hover:underline" onclick="return confirm('Delete?')">Delete</button>
+                                    </form>
+                                </td>
+                            </tr>
+                        @empty
+                            <tr>
+                                <td class="p-2" colspan="{{ count($fields)+1 }}">No {{ tableName }} found.</td>
+                            </tr>
+                        @endforelse
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    </div>
+</x-app-layout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/stubs/show.stub	Sun May 11 21:03:51 2025 -0400
@@ -0,0 +1,26 @@
+<x-app-layout>
+    <x-slot name="header">
+        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
+            {{ ucfirst('{{ modelVariable }}') }} Details
+        </h2>
+    </x-slot>
+
+    <div class="py-12">
+        <div class="max-w-2xl mx-auto sm:px-6 lg:px-8">
+            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg p-6">
+                <div class="space-y-4">
+                    @foreach($fields as $field)
+                        <div>
+                            <span class="font-semibold">{{ ucfirst($field) }}:</span>
+                            <span class="ml-2">{{ $item->$field }}</span>
+                        </div>
+                    @endforeach
+                </div>
+                <div class="flex justify-end mt-6">
+                    <a href="{{ route('{{ tableName }}.edit', $item) }}" class="mr-2 px-4 py-2 bg-yellow-400 text-white rounded hover:bg-yellow-500">Edit</a>
+                    <a href="{{ route('{{ tableName }}.index') }}" class="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300">Back</a>
+                </div>
+            </div>
+        </div>
+    </div>
+</x-app-layout>
--- a/src/MagicForgerServiceProvider.php	Tue Apr 22 21:37:44 2025 -0400
+++ b/src/MagicForgerServiceProvider.php	Sun May 11 21:03:51 2025 -0400
@@ -10,6 +10,10 @@
 use Wizard\MagicForger\Generator\Requests\StoreRequestGenerator;
 use Wizard\MagicForger\Generator\Requests\UpdateRequestGenerator;
 use Wizard\MagicForger\Generator\Route\RouteGenerator;
+use Wizard\MagicForger\Generator\View\ViewGenerator;
+use Wizard\MagicForger\Generator\View\IndexViewGenerator;
+use Wizard\MagicForger\Generator\View\CreateEditViewGenerator;
+use Wizard\MagicForger\Generator\View\ShowViewGenerator;
 
 class MagicForgerServiceProvider extends ServiceProvider
 {
@@ -27,6 +31,10 @@
                 StoreRequestGenerator::class,
                 UpdateRequestGenerator::class,
                 RouteGenerator::class,
+                ViewGenerator::class,
+                IndexViewGenerator::class,
+                CreateEditViewGenerator::class,
+                ShowViewGenerator::class,
             ]);
         }
 
--- a/src/Replacer/Replacer.php	Tue Apr 22 21:37:44 2025 -0400
+++ b/src/Replacer/Replacer.php	Sun May 11 21:03:51 2025 -0400
@@ -114,6 +114,30 @@
         return 'Update'.$this->model_name($name).'Request';
     }
 
+
+    /**
+     * Generate the index view name.
+     */
+    public function index_view_name(string $name): string
+    {
+        return '';
+    }
+
+    /**
+     * Generate the create_edit view name.
+     */
+    public function create_edit_view_name(string $name): string
+    {
+        return '';
+    }
+
+    /**
+     * Generate the show view name.
+     */
+    public function show_view_name(string $name): string
+    {
+        return '';
+    }
     // Namespace Methods
     // These methods handle the formation of various namespaces used within the replacements.
 
@@ -174,6 +198,39 @@
     }
 
     /**
+     * Get the view namespace.
+     */
+    public function getViewNamespace(string $name): string
+    {
+        return $this->viewPath($name) . '\\';
+    }
+
+    /**
+     * Get the index view namespace.
+     */
+    public function getIndexViewNamespace(string $name): string
+    {
+        return $this->getViewNamespace($name) . '\\';
+    }
+
+    /**
+     * Get the create_edit view namespace.
+     */
+    public function getCreateEditViewNamespace(string $name): string
+    {
+        return $this->getViewNamespace($name) . '\\';
+    }
+
+    /**
+     * Get the show view namespace.
+     */
+    public function getShowViewNamespace(string $name): string
+    {
+        return $this->getViewNamespace($name) . '\\';
+    }
+
+
+    /**
      * Get the request uses string for replacement.
      */
     public function getRequestUses(string $name): string