From 0531ff320deb6688855defe1b639e2a8d5ba9d23 Mon Sep 17 00:00:00 2001 From: Juzaweb Date: Fri, 11 Aug 2023 23:33:53 +0700 Subject: [PATCH] :construction: Make new theme UI --- .../Commands/Theme/ThemeGeneratorCommand.php | 71 ++++++++++++------- .../Http/Controllers/ThemeController.php | 35 ++++++++- .../Http/Requests/Theme/StoreRequest.php | 24 +++++++ .../js/components/form/buttons/button.tsx | 2 +- resources/js/components/form/inputs/input.tsx | 5 ++ .../js/components/form/inputs/textarea.tsx | 9 ++- .../pages/dev-tool/components/top-options.tsx | 2 +- resources/js/pages/dev-tool/theme/create.tsx | 47 ++++++++++-- 8 files changed, 161 insertions(+), 34 deletions(-) create mode 100644 modules/DevTool/Http/Requests/Theme/StoreRequest.php diff --git a/modules/DevTool/Commands/Theme/ThemeGeneratorCommand.php b/modules/DevTool/Commands/Theme/ThemeGeneratorCommand.php index e2abd4d05..8f4b0b952 100644 --- a/modules/DevTool/Commands/Theme/ThemeGeneratorCommand.php +++ b/modules/DevTool/Commands/Theme/ThemeGeneratorCommand.php @@ -6,6 +6,8 @@ use Illuminate\Contracts\Filesystem\FileNotFoundException; use Illuminate\Support\Facades\File; use Illuminate\Support\Str; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; class ThemeGeneratorCommand extends Command { @@ -14,7 +16,7 @@ class ThemeGeneratorCommand extends Command * * @var string */ - protected $signature = 'theme:make {name}'; + protected $name = 'theme:make {name}'; /** * The console command description. @@ -35,14 +37,14 @@ class ThemeGeneratorCommand extends Command * * @var array */ - protected $theme; + protected array $theme; /** * Created Theme Structure. * * @var array */ - protected $themeFolders; + protected array $themeFolders; /** * Theme Stubs. @@ -51,7 +53,7 @@ class ThemeGeneratorCommand extends Command */ protected string $themeStubPath; - public function handle() + public function handle(): void { $this->themePath = config('juzaweb.theme.path'); $this->themeFolders = config('theme.stubs.folders'); @@ -64,13 +66,14 @@ public function handle() * Theme Initialize. * * @return void + * @throws FileNotFoundException */ protected function init(): void { - $createdThemePath = $this->themePath . '/' . $this->theme['name']; + $createdThemePath = $this->themePath.'/'.$this->theme['name']; if (File::isDirectory($createdThemePath)) { - $this->error('Sorry Boss '. ucfirst($this->theme['name']) .' Theme Folder Already Exist !!!'); + $this->error('Sorry Boss '.ucfirst($this->theme['name']).' Theme Folder Already Exist !!!'); exit(); } @@ -78,7 +81,7 @@ protected function init(): void $themeStubFiles = config('theme.stubs.files'); $themeStubFiles['theme'] = 'theme.json'; - $themeStubFiles['changelog'] = 'changelog.yml'; + $themeStubFiles['changelog'] = 'changelog.md'; $this->makeDir($createdThemePath); foreach ($this->themeFolders as $key => $folder) { @@ -97,23 +100,24 @@ protected function init(): void */ public function generateThemeInfo(): void { - $this->theme['title'] = Str::ucfirst($this->theme['name']); - $this->theme['description'] = Str::ucfirst($this->theme['name']) . ' description'; - $this->theme['author'] = 'Author Name'; - $this->theme['version'] = '1.0'; + $this->theme['title'] = $this->option('title') ?? Str::ucfirst($this->theme['name']); + $this->theme['description'] = $this->option('description') + ?? Str::ucfirst($this->theme['name']).' description'; + $this->theme['author'] = $this->option('author'); + $this->theme['version'] = $this->option('version'); $this->theme['parent'] = ''; } /** * Make directory. * - * @param string $directory + * @param string $directory * * @return void */ protected function makeDir(string $directory): void { - if (! File::isDirectory($directory)) { + if (!File::isDirectory($directory)) { File::makeDirectory($directory, 0755, true); } } @@ -121,20 +125,21 @@ protected function makeDir(string $directory): void /** * Create theme stubs. * - * @param array $themeStubFiles - * @param string $createdThemePath + * @param array $themeStubFiles + * @param string $createdThemePath + * @throws FileNotFoundException */ - public function createStubs($themeStubFiles, $createdThemePath) + public function createStubs($themeStubFiles, $createdThemePath): void { foreach ($themeStubFiles as $filename => $storePath) { if ($filename == 'changelog') { - $filename = 'changelog' . pathinfo($storePath, PATHINFO_EXTENSION); + $filename = 'changelog'.pathinfo($storePath, PATHINFO_EXTENSION); } elseif ($filename == 'theme') { $filename = pathinfo($storePath, PATHINFO_EXTENSION); } elseif ($filename == 'css' || $filename == 'js') { $this->theme[$filename] = ltrim( $storePath, - rtrim('assets', '/') . '/' + rtrim('assets', '/').'/' ); } @@ -146,12 +151,13 @@ public function createStubs($themeStubFiles, $createdThemePath) /** * Make file. * - * @param string $file - * @param string $storePath + * @param string $file + * @param string $storePath * * @return void + * @throws FileNotFoundException */ - protected function makeFile($file, $storePath) + protected function makeFile($file, $storePath): void { if (File::exists($file)) { $content = $this->replaceStubs(File::get($file)); @@ -162,11 +168,11 @@ protected function makeFile($file, $storePath) /** * Replace Stub string. * - * @param string $contents + * @param string $contents * * @return string */ - protected function replaceStubs($contents) + protected function replaceStubs($contents): string { $mainString = [ '[NAME]', @@ -192,6 +198,23 @@ protected function replaceStubs($contents) protected function getThemeStubPath(): string { - return __DIR__ . '/../../stubs/theme'; + return __DIR__.'/../../stubs/theme'; + } + + protected function getArguments(): array + { + return [ + ['name', InputArgument::REQUIRED, 'Theme Name'], + ]; + } + + protected function getOptions(): array + { + return [ + ['title', null, InputOption::VALUE_OPTIONAL, 'Theme Title'], + ['description', null, InputOption::VALUE_OPTIONAL, 'Theme Description'], + ['author', null, InputOption::VALUE_OPTIONAL, 'Theme Author', 'Author Name'], + ['version', null, InputOption::VALUE_OPTIONAL, 'Theme Version', '1.0'], + ]; } } diff --git a/modules/DevTool/Http/Controllers/ThemeController.php b/modules/DevTool/Http/Controllers/ThemeController.php index 4d6e33237..b243e1c5a 100644 --- a/modules/DevTool/Http/Controllers/ThemeController.php +++ b/modules/DevTool/Http/Controllers/ThemeController.php @@ -11,9 +11,14 @@ namespace Juzaweb\DevTool\Http\Controllers; use Illuminate\Contracts\View\View; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Artisan; use Inertia\Response; use Juzaweb\CMS\Contracts\LocalThemeRepositoryContract; +use Juzaweb\DevTool\Http\Requests\Theme\StoreRequest; +use Symfony\Component\Console\Output\BufferedOutput; class ThemeController extends Controller { @@ -50,7 +55,7 @@ public function edit(Request $request, string $name): View|Response ); } - public function create() + public function create(): View|Response { $title = "Make new themes"; $configs = $this->getConfigs('themes'); @@ -60,4 +65,32 @@ public function create() compact('configs', 'title') ); } + + public function store(StoreRequest $request): JsonResponse|RedirectResponse + { + $outputBuffer = new BufferedOutput(); + + try { + Artisan::call( + 'theme:make', + [ + 'name' => $request->input('name'), + 'title' => $request->input('title'), + 'description' => $request->input('description'), + 'author' => $request->input('author'), + 'version' => $request->input('version'), + ], + $outputBuffer + ); + } catch (\Throwable $e) { + return $this->error($e->getMessage()); + } + + return $this->success( + [ + 'message' => 'New theme created successfully!', + 'output' => $outputBuffer->fetch(), + ] + ); + } } diff --git a/modules/DevTool/Http/Requests/Theme/StoreRequest.php b/modules/DevTool/Http/Requests/Theme/StoreRequest.php new file mode 100644 index 000000000..cc64a6fd3 --- /dev/null +++ b/modules/DevTool/Http/Requests/Theme/StoreRequest.php @@ -0,0 +1,24 @@ + ['required', 'string'], + 'title' => ['required', 'string'], + ]; + } +} diff --git a/resources/js/components/form/buttons/button.tsx b/resources/js/components/form/buttons/button.tsx index e9f1efbff..9d13a8a69 100644 --- a/resources/js/components/form/buttons/button.tsx +++ b/resources/js/components/form/buttons/button.tsx @@ -13,7 +13,7 @@ export default function Button(props: ButtonProps) {
{__('Make New Theme')} diff --git a/resources/js/pages/dev-tool/theme/create.tsx b/resources/js/pages/dev-tool/theme/create.tsx index f94d76c80..6e6a683a9 100644 --- a/resources/js/pages/dev-tool/theme/create.tsx +++ b/resources/js/pages/dev-tool/theme/create.tsx @@ -4,6 +4,8 @@ import {useState} from "react"; import Button from "@/components/form/buttons/button"; import Input from "@/components/form/inputs/input"; import Textarea from "@/components/form/inputs/textarea"; +import axios from "axios"; +import {admin_url} from "@/helpers/functions"; export default function Create() { const [buttonLoading, setButtonLoading] = useState(false); @@ -11,10 +13,18 @@ export default function Create() { status: boolean, message: string }>(); + const [outputBuffer, setOutputBuffer] = useState(); const handleMakeTheme = (e: any ) => { e.preventDefault(); + setButtonLoading(true); + + axios.post(admin_url(`/dev-tools/themes`), {}).then((res) => { + setButtonLoading(false); + setMessage(res.data); + setOutputBuffer(res.data.data.output); + }); } return ( @@ -32,19 +42,44 @@ export default function Create() {
)} + {outputBuffer && ( +
{outputBuffer}
+ )} +
- + - + -