From c94ec060b3e26e374e6e093a0dc89348f7362587 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Fri, 20 Oct 2023 16:45:22 +0200 Subject: [PATCH 01/50] Add a tips banner to the realtime compiler dashboard --- config/hyde.php | 1 + packages/framework/config/hyde.php | 1 + .../resources/dashboard.blade.php | 10 ++++++++++ .../src/Http/DashboardController.php | 20 +++++++++++++++++++ 4 files changed, 32 insertions(+) diff --git a/config/hyde.php b/config/hyde.php index d744efa2e8e..72f523de363 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -407,6 +407,7 @@ 'host' => env('SERVER_HOST', 'localhost'), 'dashboard' => env('SERVER_DASHBOARD', true), 'save_preview' => true, + 'tips' => true, ], /* diff --git a/packages/framework/config/hyde.php b/packages/framework/config/hyde.php index d744efa2e8e..72f523de363 100644 --- a/packages/framework/config/hyde.php +++ b/packages/framework/config/hyde.php @@ -407,6 +407,7 @@ 'host' => env('SERVER_HOST', 'localhost'), 'dashboard' => env('SERVER_DASHBOARD', true), 'save_preview' => true, + 'tips' => true, ], /* diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index fed651f3e40..11b18db36df 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -95,6 +95,16 @@ + @if($dashboard->showTips()) +
+
+
+ Tip: + {{ $dashboard->getTip() }} +
+
+
+ @endif +@if($dashboard->enableEditor()) + +@endif From 706151d5d7dc85093a12862c076910a3f8ea958c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Fri, 20 Oct 2023 20:36:58 +0200 Subject: [PATCH 06/50] Update dashboard Bootstrap to v5.3.2 --- packages/realtime-compiler/resources/dashboard.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 9e7cbcb957b..c377b520c8f 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -4,7 +4,7 @@ - + {{ $title }} From bf94918544f1f8a0830de7e7a90a274b3bf70f20 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Fri, 20 Oct 2023 20:38:08 +0200 Subject: [PATCH 07/50] Add Bootstrap script to dashboard --- packages/realtime-compiler/resources/dashboard.blade.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index c377b520c8f..05cf27bb8de 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -127,6 +127,9 @@ @if($dashboard->enableEditor()) + {{-- Interactivity is not needed when editor is disabled --}} + + + + + + + @endif +
From e6171255a4f7b8992d7f72673f7b961754237352 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 11:53:56 +0200 Subject: [PATCH 09/50] Create base page creation form backend --- .../src/Http/DashboardController.php | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index ea85c49af65..11bca08ab1c 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -6,9 +6,13 @@ use Hyde\Hyde; use OutOfBoundsException; +use Hyde\Pages\BladePage; use Illuminate\Support\Str; use Illuminate\Support\Arr; +use Hyde\Pages\MarkdownPage; +use Hyde\Pages\MarkdownPost; use Hyde\Pages\Concerns\HydePage; +use Hyde\Pages\DocumentationPage; use Illuminate\Support\HtmlString; use Hyde\Foundation\Facades\Routes; use Illuminate\Support\Facades\Process; @@ -16,6 +20,8 @@ use Hyde\Framework\Actions\AnonymousViewCompiler; use Desilva\Microserve\Request; use Composer\InstalledVersions; +use Hyde\Framework\Actions\CreatesNewPageSourceFile; +use Hyde\Framework\Actions\CreatesNewMarkdownPostFile; use Symfony\Component\HttpKernel\Exception\HttpException; use function abort; @@ -62,6 +68,7 @@ protected function handlePostRequest(): void { $actions = array_combine($actions = [ 'openInEditor', + 'createPage', ], $actions); $action = $this->request->data['action'] ?? abort(400, 'Must provide action'); @@ -72,6 +79,10 @@ protected function handlePostRequest(): void $page = Routes::getOrFail($routeKey)->getPage(); $this->openInEditor($page); } + + if ($action === 'createPage') { + $this->createPage(); + } } public function show(): string @@ -174,6 +185,38 @@ protected function openInEditor(HydePage $page): void } } + protected function createPage(): void + { + if ($this->enableEditor()) { + // Required data + $title = $this->request->data['titleInput'] ?? abort(400, 'Must provide title'); + $content = $this->request->data['contentInput'] ?? abort(400, 'Must provide content'); + $pageType = $this->request->data['pageTypeSelection'] ?? abort(400, 'Must provide page type'); + + // Optional data + $postDescription = $this->request->data['postDescription'] ?? null; + $postCategory = $this->request->data['postCategory'] ?? null; + $postAuthor = $this->request->data['postAuthor'] ?? null; + $postDate = $this->request->data['postDate'] ?? null; + + // Match page class + $pageClass = match ($pageType) { + 'blade-page' => BladePage::class, + 'markdown-page' => MarkdownPage::class, + 'markdown-post' => MarkdownPost::class, + 'documentation-page' => DocumentationPage::class, + default => throw new HttpException(400, "Invalid page type '$pageType'"), + }; + + if ($pageClass === MarkdownPost::class) { + $creator = new CreatesNewMarkdownPostFile($title, $postDescription, $postCategory, $postAuthor, $postDate, $content); + } else { + $creator = new CreatesNewPageSourceFile($title, $pageClass, false, $content); + } + $creator->save(); + } + } + protected static function injectDashboardButton(string $contents): string { return str_replace('', sprintf('%s', self::button()), $contents); From 0940736c759a4f9cc66ffe521393df7c58ddcb45 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 12:25:08 +0200 Subject: [PATCH 10/50] Improve asynchronous dashboard API handling --- .../resources/dashboard.blade.php | 3 + .../src/Http/DashboardController.php | 60 +++++++++++++++---- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 21d05805f54..1f81da47d40 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -287,6 +287,9 @@ fetch("", { method: "POST", body: new FormData(event.target), + headers: new Headers({ + "X-RC-Handler": "Async", + }), }).then(response => { if (response.ok) { // Request was successful, no need to do anything. diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 11bca08ab1c..9c7279c134a 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -15,16 +15,17 @@ use Hyde\Pages\DocumentationPage; use Illuminate\Support\HtmlString; use Hyde\Foundation\Facades\Routes; +use Desilva\Microserve\JsonResponse; use Illuminate\Support\Facades\Process; use Hyde\Framework\Actions\StaticPageBuilder; use Hyde\Framework\Actions\AnonymousViewCompiler; use Desilva\Microserve\Request; use Composer\InstalledVersions; use Hyde\Framework\Actions\CreatesNewPageSourceFile; +use Hyde\Framework\Exceptions\FileConflictException; use Hyde\Framework\Actions\CreatesNewMarkdownPostFile; use Symfony\Component\HttpKernel\Exception\HttpException; -use function abort; use function basename; use function array_combine; use function escapeshellarg; @@ -41,6 +42,7 @@ class DashboardController public string $title; protected Request $request; + protected bool $isAsync = false; protected static array $tips = [ 'This dashboard won\'t be saved to your static site.', @@ -56,11 +58,21 @@ public function __construct() $this->request = Request::capture(); if ($this->request->method === 'POST') { + $this->isAsync = (getallheaders()['X-RC-Handler'] ?? getallheaders()['x-rc-handler'] ?? null) === 'Async'; + if (! $this->enableEditor()) { - abort(403, 'Enable `server.editor` in `config/hyde.php` to use interactive dashboard features.'); + $this->abort(403, 'Enable `server.editor` in `config/hyde.php` to use interactive dashboard features.'); } - $this->handlePostRequest(); + try { + $this->handlePostRequest(); + } catch (HttpException $exception) { + if (! $this->isAsync) { + throw $exception; + } + + $this->sendJsonResponse($exception); + } } } @@ -71,11 +83,11 @@ protected function handlePostRequest(): void 'createPage', ], $actions); - $action = $this->request->data['action'] ?? abort(400, 'Must provide action'); - $action = $actions[$action] ?? abort(403, 'Invalid action'); + $action = $this->request->data['action'] ?? $this->abort(400, 'Must provide action'); + $action = $actions[$action] ?? $this->abort(403, "Invalid action '$action'"); if ($action === 'openInEditor') { - $routeKey = $this->request->data['routeKey'] ?? abort(400, 'Must provide routeKey'); + $routeKey = $this->request->data['routeKey'] ?? $this->abort(400, 'Must provide routeKey'); $page = Routes::getOrFail($routeKey)->getPage(); $this->openInEditor($page); } @@ -178,7 +190,7 @@ protected function openInEditor(HydePage $page): void $path = Hyde::path($page->getSourcePath()); if (! (str_ends_with($path, '.md') || str_ends_with($path, '.blade.php'))) { - abort(403, sprintf("Refusing to open unsafe file '%s'", basename($path))); + $this->abort(403, sprintf("Refusing to open unsafe file '%s'", basename($path))); } Process::run(sprintf('%s %s', $binary, escapeshellarg($path)))->throw(); @@ -189,9 +201,9 @@ protected function createPage(): void { if ($this->enableEditor()) { // Required data - $title = $this->request->data['titleInput'] ?? abort(400, 'Must provide title'); - $content = $this->request->data['contentInput'] ?? abort(400, 'Must provide content'); - $pageType = $this->request->data['pageTypeSelection'] ?? abort(400, 'Must provide page type'); + $title = $this->request->data['titleInput'] ?? $this->abort(400, 'Must provide title'); + $content = $this->request->data['contentInput'] ?? $this->abort(400, 'Must provide content'); + $pageType = $this->request->data['pageTypeSelection'] ?? $this->abort(400, 'Must provide page type'); // Optional data $postDescription = $this->request->data['postDescription'] ?? null; @@ -213,7 +225,11 @@ protected function createPage(): void } else { $creator = new CreatesNewPageSourceFile($title, $pageClass, false, $content); } - $creator->save(); + try { + $creator->save(); + } catch (FileConflictException $exception) { + $this->abort($exception->getCode(), $exception->getMessage()); + } } } @@ -303,4 +319,26 @@ protected static function getPackageVersion(string $packageName): string return $prettyVersion ?? 'unreleased'; } + + protected function sendJsonResponse(HttpException $exception): never + { + $statusMessage = match ($exception->getStatusCode()) { + 200 => 'OK', + 201 => 'Created', + 400 => 'Bad Request', + 403 => 'Forbidden', + 409 => 'Conflict', + default => 'Internal Server Error', + }; + (new JsonResponse($exception->getStatusCode(), $statusMessage, [ + 'error' => $exception->getMessage(), + ]))->send(); + + exit; + } + + protected function abort(int $code, string $message): never + { + throw new HttpException($code, $message); + } } From 25e96dd3e7270d4963f4662343887ace7b58788c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 12:50:39 +0200 Subject: [PATCH 11/50] Disable submit until ready --- packages/realtime-compiler/resources/dashboard.blade.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 1f81da47d40..78250ee8d90 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -140,7 +140,7 @@ Send feedback - + @endif From b901dbd9aa1b10169642ac1b4652b4860fc6d64e Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 13:55:21 +0200 Subject: [PATCH 13/50] Improve async form handler --- .../resources/dashboard.blade.php | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 198533c7e91..8279abf7eac 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -280,13 +280,22 @@ /** * Progressive enhancement when JavaScript is enabled to intercept form requests * and instead handle them with an asynchronous Fetch instead of refreshing the page. + * + * @param {Element} form + * @param {?callback} okHandler + * @param {?callback} errorHandler + * @param {?callback} beforeCallHandler + * @param {?callback} afterCallHandler */ - - function registerAsyncForm(form) { + function registerAsyncForm(form, okHandler = null, errorHandler = null, beforeCallHandler = null, afterCallHandler = null) { form.addEventListener("submit", function (event) { // Disable default form submit event.preventDefault(); + if (beforeCallHandler) { + beforeCallHandler(); + } + fetch("", { method: "POST", body: new FormData(event.target), @@ -295,15 +304,24 @@ function registerAsyncForm(form) { }), }).then(response => { if (response.ok) { - // Request was successful, no need to do anything. + if (okHandler) { + okHandler(response); + } } else { - // Request failed, let's log it. - console.error("Fetch request failed."); + if (errorHandler) { + errorHandler(response); + } else { + console.error("Fetch request failed."); + } } }).catch(error => { // Handle any network-related errors console.error("Network error:", error); }); + + if (afterCallHandler) { + afterCallHandler(); + } }); } From 539e6b2f984d21e8791027e024d1c01af300b582 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 14:28:55 +0200 Subject: [PATCH 14/50] Split out method --- .../src/Http/DashboardController.php | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 9c7279c134a..5afe1cb133c 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -71,7 +71,7 @@ public function __construct() throw $exception; } - $this->sendJsonResponse($exception); + $this->sendJsonErrorResponse($exception); } } } @@ -320,16 +320,30 @@ protected static function getPackageVersion(string $packageName): string return $prettyVersion ?? 'unreleased'; } - protected function sendJsonResponse(HttpException $exception): never + protected function sendJsonResponse(int $statusCode, string $body): never { - $statusMessage = match ($exception->getStatusCode()) { + $statusMessage = match ($statusCode) { 200 => 'OK', 201 => 'Created', + default => 'Internal Server Error', + }; + + (new JsonResponse($statusCode, $statusMessage, [ + 'body' => $body, + ]))->send(); + + exit; + } + + protected function sendJsonErrorResponse(HttpException $exception): never + { + $statusMessage = match ($exception->getStatusCode()) { 400 => 'Bad Request', 403 => 'Forbidden', 409 => 'Conflict', default => 'Internal Server Error', }; + (new JsonResponse($exception->getStatusCode(), $statusMessage, [ 'error' => $exception->getMessage(), ]))->send(); From f57c822cbfd399d8ccee65e2ac6a3441b42f7136 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 14:45:40 +0200 Subject: [PATCH 15/50] Create async create page modal interactivity --- .../resources/dashboard.blade.php | 41 ++++++++++++++++++- .../src/Http/DashboardController.php | 4 +- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 8279abf7eac..117db116736 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -75,10 +75,14 @@

Create new page

-
+
@if($dashboard->enableEditor()) - + diff --git a/packages/realtime-compiler/resources/dashboard.js b/packages/realtime-compiler/resources/dashboard.js index cfd31ed20d9..6b32c290e86 100644 --- a/packages/realtime-compiler/resources/dashboard.js +++ b/packages/realtime-compiler/resources/dashboard.js @@ -90,7 +90,7 @@ function registerCreateFormModalHandlers() { registerAsyncForm(createPageForm, okHandler, errorHandler, beforeCallHandler, afterCallHandler); } -document.querySelectorAll(".openInEditorForm").forEach(form => { +document.querySelectorAll(".buttonActionForm").forEach(form => { registerAsyncForm(form); }); From 679164bd2b57557a23c9b76fe469cee9dfe3195e Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 21:56:52 +0200 Subject: [PATCH 24/50] Add action to open folder in explorer --- .../resources/dashboard.blade.php | 10 +++++++++- .../src/Http/DashboardController.php | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index b9270e1c5c3..b172ee4a29f 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -37,7 +37,15 @@
-

Project Information

+
+

Site Pages & Routes

+ @if($dashboard->enableEditor()) + + + + + @endif +
diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 3ddebc9b32e..689b63d672c 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -79,6 +79,7 @@ public function __construct() protected function handlePostRequest(): void { $actions = array_combine($actions = [ + 'openInExplorer', 'openInEditor', 'createPage', ], $actions); @@ -86,6 +87,10 @@ protected function handlePostRequest(): void $action = $this->request->data['action'] ?? $this->abort(400, 'Must provide action'); $action = $actions[$action] ?? $this->abort(403, "Invalid action '$action'"); + if ($action === 'openInExplorer') { + $this->openInExplorer(); + } + if ($action === 'openInEditor') { $routeKey = $this->request->data['routeKey'] ?? $this->abort(400, 'Must provide routeKey'); $page = Routes::getOrFail($routeKey)->getPage(); @@ -183,6 +188,21 @@ public function getScripts(): string return file_get_contents(__DIR__.'/../../resources/dashboard.js'); } + protected function openInExplorer(): void + { + if ($this->enableEditor()) { + $binary = match (PHP_OS_FAMILY) { + 'Windows' => 'powershell Start-Process', // Using PowerShell allows us to open the file in the background + 'Darwin' => 'open', + 'Linux' => 'xdg-open', + default => throw new HttpException(500, sprintf("Unable to find a matching binary for OS family '%s'", PHP_OS_FAMILY)) + }; + $path = Hyde::path(); + + Process::run(sprintf('%s %s', $binary, escapeshellarg($path)))->throw(); + } + } + protected function openInEditor(HydePage $page): void { if ($this->enableEditor()) { From 88606586c2d8dbc9490cd810dd5116338eefe3d6 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 22:47:40 +0200 Subject: [PATCH 25/50] Replace dashboard SweetAlert with custom session flashing --- .../resources/dashboard.blade.php | 17 ++++++++++-- .../realtime-compiler/resources/dashboard.js | 12 +++------ .../src/Http/DashboardController.php | 27 +++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index b172ee4a29f..0823678ebe2 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -7,6 +7,20 @@ {{ $title }} + @foreach($dashboard->getPageList() as $route) - + getFlash('justCreatedPage') === $route->getRouteKey() ? 'justCreatedPage active' : ''])> @@ -287,7 +301,6 @@ @if($dashboard->enableEditor()) {{-- Interactivity is not needed when editor is disabled --}} - @endif diff --git a/packages/realtime-compiler/resources/dashboard.js b/packages/realtime-compiler/resources/dashboard.js index 6b32c290e86..5f28d747d12 100644 --- a/packages/realtime-compiler/resources/dashboard.js +++ b/packages/realtime-compiler/resources/dashboard.js @@ -61,14 +61,10 @@ function registerCreateFormModalHandlers() { const okHandler = async response => { let data = await response.json(); createPageModal.hide(); - Swal.fire({ - title: 'Page created!', - text: data.body, - icon: 'success', - timer: 3000, - timerProgressBar: true, - }) - createPageForm.reset() + createPageForm.reset(); + + // Reload so new page shows up in the table + location.reload(); }; const errorHandler = async response => { diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 689b63d672c..6e12aebe378 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -13,6 +13,7 @@ use Hyde\Pages\MarkdownPost; use Hyde\Pages\Concerns\HydePage; use Hyde\Pages\DocumentationPage; +use Hyde\Support\Models\RouteKey; use Illuminate\Support\HtmlString; use Hyde\Foundation\Facades\Routes; use Desilva\Microserve\JsonResponse; @@ -26,7 +27,10 @@ use Hyde\Framework\Actions\CreatesNewMarkdownPostFile; use Symfony\Component\HttpKernel\Exception\HttpException; +use function time; use function basename; +use function json_decode; +use function json_encode; use function array_combine; use function escapeshellarg; use function file_get_contents; @@ -44,6 +48,8 @@ class DashboardController protected Request $request; protected bool $isAsync = false; + protected array $flashes = []; + protected static array $tips = [ 'This dashboard won\'t be saved to your static site.', 'Got stuck? Ask for help on [GitHub](https://github.com/hydephp/hyde)!', @@ -57,6 +63,8 @@ public function __construct() $this->title = config('hyde.name').' - Dashboard'; $this->request = Request::capture(); + $this->loadFlashData(); + if ($this->request->method === 'POST') { $this->isAsync = (getallheaders()['X-RC-Handler'] ?? getallheaders()['x-rc-handler'] ?? null) === 'Async'; @@ -188,6 +196,24 @@ public function getScripts(): string return file_get_contents(__DIR__.'/../../resources/dashboard.js'); } + public function getFlash(string $key, $default = null): ?string + { + return $this->flashes[$key] ?? $default; + } + + protected function flash(string $string, string $value): void + { + setcookie('hyde-rc-flash', json_encode([$string => $value]), time() + 180, '/') ?: $this->abort(500, 'Failed to flash session cookie'); + } + + protected function loadFlashData(): void + { + if ($flashData = $_COOKIE['hyde-rc-flash'] ?? null) { + $this->flashes = json_decode($flashData, true); + setcookie('hyde-rc-flash', ''); // Clear cookie + } + } + protected function openInExplorer(): void { if ($this->enableEditor()) { @@ -256,6 +282,7 @@ protected function createPage(): void $this->abort($exception->getCode(), $exception->getMessage()); } + $this->flash('justCreatedPage', RouteKey::fromPage($pageClass, $pageClass::pathToIdentifier($path))->get()); $this->sendJsonResponse(201, "Created file '$path'!"); } } From 15a22d1819effd61e28debb2bce1de3661897c21 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 22:50:36 +0200 Subject: [PATCH 26/50] Move script to function in file --- .../resources/dashboard.blade.php | 57 ------------------ .../realtime-compiler/resources/dashboard.js | 60 +++++++++++++++++++ 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 0823678ebe2..e259349e5ae 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -168,63 +168,6 @@ - diff --git a/packages/realtime-compiler/resources/dashboard.js b/packages/realtime-compiler/resources/dashboard.js index 5f28d747d12..56dd5dacf9b 100644 --- a/packages/realtime-compiler/resources/dashboard.js +++ b/packages/realtime-compiler/resources/dashboard.js @@ -86,8 +86,68 @@ function registerCreateFormModalHandlers() { registerAsyncForm(createPageForm, okHandler, errorHandler, beforeCallHandler, afterCallHandler); } +function handleModalInteractivity() { + // Focus when modal is opened + const modal = document.getElementById('createPageModal') + const firstInput = document.getElementById('pageTypeSelection') + + modal.addEventListener('shown.bs.modal', () => { + firstInput.focus() + }) + + // Handle form interactivity + + const createPageModalLabel = document.getElementById('createPageModalLabel'); + const titleInputLabel = document.getElementById('titleInputLabel'); + const contentInputLabel = document.getElementById('contentInputLabel'); + + const contentInput = document.getElementById('contentInput'); + const pageTypeSelection = document.getElementById('pageTypeSelection'); + const createPageButton = document.getElementById('createPageButton'); + + const baseInfo = document.getElementById('baseInfo'); + const createsPost = document.getElementById('createsPost'); + + const createPageModalLabelDefault = createPageModalLabel.innerText; + const titleInputLabelDefault = titleInputLabel.innerText; + const contentInputLabelDefault = contentInputLabel.innerText; + const contentInputPlaceholderDefault = contentInput.placeholder; + + pageTypeSelection.addEventListener('change', function (event) { + createPageModalLabel.innerText = createPageModalLabelDefault; + titleInputLabel.innerText = titleInputLabelDefault; + contentInputLabel.innerText = contentInputLabelDefault; + contentInput.placeholder = contentInputPlaceholderDefault; + + createPageButton.disabled = false; + createPageButton.title = ''; + + baseInfo.style.display = 'none'; + createsPost.style.display = 'none'; + + let selection = event.target.value; + + if (selection === 'markdown-post') { + baseInfo.style.display = 'block'; + createsPost.style.display = 'block'; + createPageModalLabel.innerText = 'Creating a new Markdown post'; + titleInputLabel.innerText = 'Post title'; + } else { + baseInfo.style.display = 'block'; + createPageModalLabel.innerText = 'Creating a new ' + selection.replace(/-/g, ' ').replace(/^\w/, c => c.toUpperCase()); + } + + if (selection === 'blade-page') { + contentInputLabel.innerText = 'Blade content'; + contentInput.placeholder = 'Enter your Blade content'; + } + }); +} + document.querySelectorAll(".buttonActionForm").forEach(form => { registerAsyncForm(form); }); registerCreateFormModalHandlers(); + +handleModalInteractivity(); From 9d65d38dc2be12e83fab90249f8058d68e818f92 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sat, 21 Oct 2023 22:51:12 +0200 Subject: [PATCH 27/50] Comment out unused data --- packages/realtime-compiler/resources/dashboard.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.js b/packages/realtime-compiler/resources/dashboard.js index 56dd5dacf9b..2e8f8da9d38 100644 --- a/packages/realtime-compiler/resources/dashboard.js +++ b/packages/realtime-compiler/resources/dashboard.js @@ -58,8 +58,8 @@ function registerCreateFormModalHandlers() { const createPageFormError = document.getElementById("createPageFormError"); const createPageFormErrorContents = document.getElementById("createPageFormErrorContents"); - const okHandler = async response => { - let data = await response.json(); + const okHandler = () => { + // let data = await response.json(); createPageModal.hide(); createPageForm.reset(); From 03a69f176b6e47ae9181c5624a6462c0269e93f4 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Oct 2023 19:18:27 +0200 Subject: [PATCH 28/50] Set dashboard button display default to true --- packages/realtime-compiler/src/Http/DashboardController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 6e12aebe378..61b061526a0 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -178,7 +178,7 @@ public static function renderIndexPage(HydePage $page): string $contents = str_replace('', sprintf("%s\n", self::welcomeFrame()), $contents); } - if (config('hyde.server.dashboard.button', false)) { + if (config('hyde.server.dashboard.button', true)) { $contents = self::injectDashboardButton($contents); } } From 1d3ef398488b9a24f66e3dfa5cf248f1450d59aa Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Oct 2023 19:21:17 +0200 Subject: [PATCH 29/50] Clarify added dashboard config keys --- config/hyde.php | 4 ++-- packages/framework/config/hyde.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/hyde.php b/config/hyde.php index 1779cadac04..c8b940f18c5 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -406,9 +406,9 @@ 'port' => env('SERVER_PORT', 8080), 'host' => env('SERVER_HOST', 'localhost'), 'dashboard' => env('SERVER_DASHBOARD', true), + 'dashboard_editor' => true, + 'dashboard_tips' => true, 'save_preview' => true, - 'editor' => true, - 'tips' => true, ], /* diff --git a/packages/framework/config/hyde.php b/packages/framework/config/hyde.php index 1779cadac04..c8b940f18c5 100644 --- a/packages/framework/config/hyde.php +++ b/packages/framework/config/hyde.php @@ -406,9 +406,9 @@ 'port' => env('SERVER_PORT', 8080), 'host' => env('SERVER_HOST', 'localhost'), 'dashboard' => env('SERVER_DASHBOARD', true), + 'dashboard_editor' => true, + 'dashboard_tips' => true, 'save_preview' => true, - 'editor' => true, - 'tips' => true, ], /* From cedc566268f08fc92b2a375d2bad4045f3f6619e Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Sun, 22 Oct 2023 19:30:45 +0200 Subject: [PATCH 30/50] Document realtime compiler config options --- config/hyde.php | 11 +++++++++++ packages/framework/config/hyde.php | 11 +++++++++++ .../src/Http/DashboardController.php | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/config/hyde.php b/config/hyde.php index c8b940f18c5..5e1d4930236 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -403,11 +403,22 @@ */ 'server' => [ + // The default port the preview is served on 'port' => env('SERVER_PORT', 8080), + + // The default host the preview is served on 'host' => env('SERVER_HOST', 'localhost'), + + // Should the realtime compiler dashboard be enabled? 'dashboard' => env('SERVER_DASHBOARD', true), + + // Can the dashboard make edits to the project file system? 'dashboard_editor' => true, + + // Should the dashboard show tips? 'dashboard_tips' => true, + + // Should preview pages be saved to the output directory? 'save_preview' => true, ], diff --git a/packages/framework/config/hyde.php b/packages/framework/config/hyde.php index c8b940f18c5..5e1d4930236 100644 --- a/packages/framework/config/hyde.php +++ b/packages/framework/config/hyde.php @@ -403,11 +403,22 @@ */ 'server' => [ + // The default port the preview is served on 'port' => env('SERVER_PORT', 8080), + + // The default host the preview is served on 'host' => env('SERVER_HOST', 'localhost'), + + // Should the realtime compiler dashboard be enabled? 'dashboard' => env('SERVER_DASHBOARD', true), + + // Can the dashboard make edits to the project file system? 'dashboard_editor' => true, + + // Should the dashboard show tips? 'dashboard_tips' => true, + + // Should preview pages be saved to the output directory? 'save_preview' => true, ], diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 61b061526a0..fac1952e72a 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -54,8 +54,8 @@ class DashboardController 'This dashboard won\'t be saved to your static site.', 'Got stuck? Ask for help on [GitHub](https://github.com/hydephp/hyde)!', 'Found a bug? Please report it on [GitHub](https://github.com/hydephp/hyde)!', - 'You can disable tips using by setting `server.tips` to `false` in `config/hyde.php`.', - 'The dashboard can make changes to your project files. You can disable this by setting `server.editor` to `false` in `config/hyde.php`.', + 'You can disable tips using by setting `server.dashboard_tips` to `false` in `config/hyde.php`.', + 'The dashboard update your project files. You can disable this by setting `server.dashboard_editor` to `false` in `config/hyde.php`.', ]; public function __construct() From f098987ad8c6a4a3c455207b3b5b887d4fa7e2f4 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Mon, 23 Oct 2023 18:00:14 +0200 Subject: [PATCH 31/50] Rename dashboard action --- packages/realtime-compiler/resources/dashboard.blade.php | 2 +- .../realtime-compiler/src/Http/DashboardController.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index e259349e5ae..bdc94b4ecf3 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -204,7 +204,7 @@
@if($dashboard->enableEditor())
- + diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index fac1952e72a..1308ff6f827 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -88,7 +88,7 @@ protected function handlePostRequest(): void { $actions = array_combine($actions = [ 'openInExplorer', - 'openInEditor', + 'openPageInEditor', 'createPage', ], $actions); @@ -99,10 +99,10 @@ protected function handlePostRequest(): void $this->openInExplorer(); } - if ($action === 'openInEditor') { + if ($action === 'openPageInEditor') { $routeKey = $this->request->data['routeKey'] ?? $this->abort(400, 'Must provide routeKey'); $page = Routes::getOrFail($routeKey)->getPage(); - $this->openInEditor($page); + $this->openPageInEditor($page); } if ($action === 'createPage') { @@ -229,7 +229,7 @@ protected function openInExplorer(): void } } - protected function openInEditor(HydePage $page): void + protected function openPageInEditor(HydePage $page): void { if ($this->enableEditor()) { $binary = match (PHP_OS_FAMILY) { From 06ff493a34a7e47e73d17011152c1b4334833d7b Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Tue, 24 Oct 2023 18:00:28 +0200 Subject: [PATCH 32/50] Create dashboard media library frontend --- .../resources/dashboard.blade.php | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index bdc94b4ecf3..a67f476121f 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -21,6 +21,7 @@ } } +
+
+
+
+
+
+

Media Library

+
+
+
+
+ @foreach(\Hyde\Support\Filesystem\MediaFile::all() as $mediaFile) +
+
+ @if(in_array($mediaFile->getExtension(), ['svg', 'png', 'jpg', 'jpeg', 'gif'])) + {{ $mediaFile->getName() }} + @else +
getContents()) > 200) ? 'white-space: normal;' : '' }}">{{ substr($mediaFile->getContents(), 0, 400) }}
+ @endif +
+
+
+
+
+
+
+

+ {{ $mediaFile->getName() }} +

+
+ ({{ $dashboard::bytesToHuman($mediaFile->getContentLength()) }}) +
+
+
+ + @if($dashboard->enableEditor()) +
+
+ + + + +
+ @endif +
+
+
+
+
+
+ @endforeach +
+
+
+
+
@if($dashboard->showTips())
From f4cf4e1d5e0a487656581c5342de7f079c79ed00 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 25 Oct 2023 18:00:42 +0200 Subject: [PATCH 33/50] Create dashboard media library backend --- .../src/Http/DashboardController.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 1308ff6f827..3c3467f9e37 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -17,6 +17,7 @@ use Illuminate\Support\HtmlString; use Hyde\Foundation\Facades\Routes; use Desilva\Microserve\JsonResponse; +use Hyde\Support\Filesystem\MediaFile; use Illuminate\Support\Facades\Process; use Hyde\Framework\Actions\StaticPageBuilder; use Hyde\Framework\Actions\AnonymousViewCompiler; @@ -28,7 +29,9 @@ use Symfony\Component\HttpKernel\Exception\HttpException; use function time; +use function round; use function basename; +use function in_array; use function json_decode; use function json_encode; use function array_combine; @@ -89,6 +92,7 @@ protected function handlePostRequest(): void $actions = array_combine($actions = [ 'openInExplorer', 'openPageInEditor', + 'openMediaFileInEditor', 'createPage', ], $actions); @@ -105,6 +109,12 @@ protected function handlePostRequest(): void $this->openPageInEditor($page); } + if ($action === 'openMediaFileInEditor') { + $identifier = $this->request->data['identifier'] ?? $this->abort(400, 'Must provide identifier'); + $asset = @MediaFile::all()[$identifier] ?? $this->abort(404, "Invalid media identifier '$identifier'"); + $this->openMediaFileInEditor($asset); + } + if ($action === 'createPage') { $this->createPage(); } @@ -140,6 +150,16 @@ public function getPageList(): array return Hyde::routes()->all(); } + /** @internal */ + public static function bytesToHuman(int $bytes, int $precision = 2): string + { + for ($i = 0; $bytes > 1024; $i++) { + $bytes /= 1024; + } + + return round($bytes, $precision).' '.['B', 'KB', 'MB', 'GB', 'TB'][$i]; + } + public function showTips(): bool { return config('hyde.server.tips', true); @@ -248,6 +268,25 @@ protected function openPageInEditor(HydePage $page): void } } + protected function openMediaFileInEditor(MediaFile $file): void + { + if ($this->enableEditor()) { + $binary = match (PHP_OS_FAMILY) { + 'Windows' => 'powershell Start-Process', // Using PowerShell allows us to open the file in the background + 'Darwin' => 'open', + 'Linux' => 'xdg-open', + default => throw new HttpException(500, sprintf("Unable to find a matching binary for OS family '%s'", PHP_OS_FAMILY)) + }; + $path = $file->getAbsolutePath(); + + if (! in_array($file->getExtension(), ['png', 'svg', 'jpg', 'jpeg', 'gif', 'ico'])) { + $this->abort(403, sprintf("Refusing to open unsafe file '%s'", basename($path))); + } + + Process::run(sprintf('%s %s', $binary, escapeshellarg($path)))->throw(); + } + } + protected function createPage(): void { if ($this->enableEditor()) { @@ -394,6 +433,7 @@ protected function sendJsonErrorResponse(HttpException $exception): never $statusMessage = match ($exception->getStatusCode()) { 400 => 'Bad Request', 403 => 'Forbidden', + 404 => 'Not Found', 409 => 'Conflict', default => 'Internal Server Error', }; From 8e0486d969b6353c1efb7da56565bdfe3b252303 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 25 Oct 2023 18:05:55 +0200 Subject: [PATCH 34/50] Extract function for repeated code segment --- .../src/Http/DashboardController.php | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 3c3467f9e37..348e8cf4262 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -237,12 +237,7 @@ protected function loadFlashData(): void protected function openInExplorer(): void { if ($this->enableEditor()) { - $binary = match (PHP_OS_FAMILY) { - 'Windows' => 'powershell Start-Process', // Using PowerShell allows us to open the file in the background - 'Darwin' => 'open', - 'Linux' => 'xdg-open', - default => throw new HttpException(500, sprintf("Unable to find a matching binary for OS family '%s'", PHP_OS_FAMILY)) - }; + $binary = $this->findGeneralOpenBinary(); $path = Hyde::path(); Process::run(sprintf('%s %s', $binary, escapeshellarg($path)))->throw(); @@ -252,12 +247,7 @@ protected function openInExplorer(): void protected function openPageInEditor(HydePage $page): void { if ($this->enableEditor()) { - $binary = match (PHP_OS_FAMILY) { - 'Windows' => 'powershell Start-Process', // Using PowerShell allows us to open the file in the background - 'Darwin' => 'open', - 'Linux' => 'xdg-open', - default => throw new HttpException(500, sprintf("Unable to find a matching binary for OS family '%s'", PHP_OS_FAMILY)) - }; + $binary = $this->findGeneralOpenBinary(); $path = Hyde::path($page->getSourcePath()); if (! (str_ends_with($path, '.md') || str_ends_with($path, '.blade.php'))) { @@ -271,12 +261,7 @@ protected function openPageInEditor(HydePage $page): void protected function openMediaFileInEditor(MediaFile $file): void { if ($this->enableEditor()) { - $binary = match (PHP_OS_FAMILY) { - 'Windows' => 'powershell Start-Process', // Using PowerShell allows us to open the file in the background - 'Darwin' => 'open', - 'Linux' => 'xdg-open', - default => throw new HttpException(500, sprintf("Unable to find a matching binary for OS family '%s'", PHP_OS_FAMILY)) - }; + $binary = $this->findGeneralOpenBinary(); $path = $file->getAbsolutePath(); if (! in_array($file->getExtension(), ['png', 'svg', 'jpg', 'jpeg', 'gif', 'ico'])) { @@ -449,4 +434,14 @@ protected function abort(int $code, string $message): never { throw new HttpException($code, $message); } + + protected function findGeneralOpenBinary(): string + { + return match (PHP_OS_FAMILY) { + 'Windows' => 'powershell Start-Process', // Using PowerShell allows us to open the file in the background + 'Darwin' => 'open', + 'Linux' => 'xdg-open', + default => throw new HttpException(500, sprintf("Unable to find a matching binary for OS family '%s'", PHP_OS_FAMILY)) + }; + } } From 9b055c8e6abb5b98c692ea429f38fbdd92a5d6b9 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 25 Oct 2023 18:05:14 +0200 Subject: [PATCH 35/50] Minify CSS --- packages/realtime-compiler/resources/dashboard.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index a67f476121f..234cfb629d8 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -21,7 +21,7 @@ } } - +
@foreach($dashboard->getProjectInformation() as $type => $info) @endforeach diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 1be3e3138d3..f3124f47cfe 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -144,10 +144,10 @@ public function getVersion(): string public function getProjectInformation(): array { return [ - 'Git Version:' => app('git.version'), - 'Hyde Version:' => self::getPackageVersion('hyde/hyde'), - 'Framework Version:' => self::getPackageVersion('hyde/framework'), - 'Project Path:' => Hyde::path(), + 'Git Version' => app('git.version'), + 'Hyde Version' => self::getPackageVersion('hyde/hyde'), + 'Framework Version' => self::getPackageVersion('hyde/framework'), + 'Project Path' => Hyde::path(), ]; } From 12f845244843bb57a9b5bcc31f74422ff381f5d7 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Thu, 26 Oct 2023 14:19:01 +0200 Subject: [PATCH 46/50] Add dashboard button to copy project path to clipboard --- .../resources/dashboard.blade.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 0a83df5284f..829bca8cd34 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -77,6 +77,35 @@ @endforeach From 66355d9e96eac35157d0b9fffabf36f5b732679f Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Thu, 26 Oct 2023 15:36:16 +0200 Subject: [PATCH 47/50] Add token to dashboard highlighter --- packages/realtime-compiler/src/Http/DashboardController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index f3124f47cfe..2f30e34b4b5 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -209,6 +209,7 @@ public static function highlightMediaLibraryCode(string $contents): HtmlString ')' => ")", ':' => ":", ';' => ";", + '+' => "+", 'return' => "return", 'function' => "function", ]); From a7e362d06299154787289c7837e661daf6bde0bc Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Thu, 26 Oct 2023 15:56:02 +0200 Subject: [PATCH 48/50] Lazy load images --- packages/realtime-compiler/resources/dashboard.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index 829bca8cd34..e212d9489d0 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -271,7 +271,7 @@
@if(in_array($mediaFile->getExtension(), ['svg', 'png', 'jpg', 'jpeg', 'gif'])) - {{ $mediaFile->getName() }} + {{ $mediaFile->getName() }} @else @if($dashboard::isMediaFileProbablyMinified($mediaFile->getContents())) From 44a88bd5f0d42558a3aedf823662b9bff3e5f175 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Thu, 26 Oct 2023 16:59:38 +0200 Subject: [PATCH 49/50] Add title to button --- packages/realtime-compiler/resources/dashboard.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index e212d9489d0..318e9f70b55 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -78,7 +78,7 @@ {{ $type }}: {{ $info }} @if($loop->last) -
Actions
{{ class_basename($route->getPageClass()) }}
- @if($dashboard->enableEditor()) + @if($dashboard->isInteractive()) @@ -262,7 +262,7 @@ - @if($dashboard->enableEditor()) + @if($dashboard->isInteractive())
@@ -305,7 +305,7 @@
-@if($dashboard->enableEditor()) +@if($dashboard->isInteractive()) {{-- Interactivity is not needed when editor is disabled --}} diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index d1f58baac18..19b91d0de2c 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -78,7 +78,7 @@ public function __construct() if ($this->request->method === 'POST') { $this->isAsync = (getallheaders()['X-RC-Handler'] ?? getallheaders()['x-rc-handler'] ?? null) === 'Async'; - if (! $this->enableEditor()) { + if (! $this->isInteractive()) { $this->abort(403, 'Enable `server.editor` in `config/hyde.php` to use interactive dashboard features.'); } @@ -264,7 +264,7 @@ public static function renderIndexPage(HydePage $page): string return $contents; } - public function enableEditor(): bool + public function isInteractive(): bool { return config('hyde.server.editor', true); } @@ -294,7 +294,7 @@ protected function loadFlashData(): void protected function openInExplorer(): void { - if ($this->enableEditor()) { + if ($this->isInteractive()) { $binary = $this->findGeneralOpenBinary(); $path = Hyde::path(); @@ -304,7 +304,7 @@ protected function openInExplorer(): void protected function openPageInEditor(HydePage $page): void { - if ($this->enableEditor()) { + if ($this->isInteractive()) { $binary = $this->findGeneralOpenBinary(); $path = Hyde::path($page->getSourcePath()); @@ -318,7 +318,7 @@ protected function openPageInEditor(HydePage $page): void protected function openMediaFileInEditor(MediaFile $file): void { - if ($this->enableEditor()) { + if ($this->isInteractive()) { $binary = $this->findGeneralOpenBinary(); $path = $file->getAbsolutePath(); @@ -332,7 +332,7 @@ protected function openMediaFileInEditor(MediaFile $file): void protected function createPage(): void { - if ($this->enableEditor()) { + if ($this->isInteractive()) { // Required data $title = $this->request->data['titleInput'] ?? $this->abort(400, 'Must provide title'); $content = $this->request->data['contentInput'] ?? $this->abort(400, 'Must provide content'); From a02e19ba7cdba49ab4919646011010ce0fbc400c Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 25 Oct 2023 22:55:56 +0200 Subject: [PATCH 41/50] Fix wrong config keys --- packages/realtime-compiler/src/Http/DashboardController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/realtime-compiler/src/Http/DashboardController.php b/packages/realtime-compiler/src/Http/DashboardController.php index 19b91d0de2c..ff6c5068817 100644 --- a/packages/realtime-compiler/src/Http/DashboardController.php +++ b/packages/realtime-compiler/src/Http/DashboardController.php @@ -220,7 +220,7 @@ public static function highlightMediaLibraryCode(string $contents): HtmlString public function showTips(): bool { - return config('hyde.server.tips', true); + return config('hyde.server.dashboard_tips', true); } public function getTip(): HtmlString @@ -266,7 +266,7 @@ public static function renderIndexPage(HydePage $page): string public function isInteractive(): bool { - return config('hyde.server.editor', true); + return config('hyde.server.dashboard_editor', true); } public function getScripts(): string From 5481f31501d45e737944f4ca5e307f874685a742 Mon Sep 17 00:00:00 2001 From: Caen De Silva Date: Wed, 25 Oct 2023 23:03:24 +0200 Subject: [PATCH 42/50] Add badge when readonly --- .../realtime-compiler/resources/dashboard.blade.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/realtime-compiler/resources/dashboard.blade.php b/packages/realtime-compiler/resources/dashboard.blade.php index d6dab02b7b8..e424a42559d 100644 --- a/packages/realtime-compiler/resources/dashboard.blade.php +++ b/packages/realtime-compiler/resources/dashboard.blade.php @@ -25,7 +25,15 @@
- {{ $type }} + {{ $type }}: {{ $info }} {{ $type }}: {{ $info }} + @if($loop->last) + + + @endif