diff --git a/front/js/svelte/Account.svelte b/front/js/svelte/Account.svelte index 71938b1..09cf17c 100644 --- a/front/js/svelte/Account.svelte +++ b/front/js/svelte/Account.svelte @@ -24,7 +24,7 @@ setContext("user", user);
-

{channel.name}

+

{channel.name ?? "Lucent Setup"}

diff --git a/front/js/svelte/setup/Index.svelte b/front/js/svelte/setup/Index.svelte index bf5d226..0c8a37f 100644 --- a/front/js/svelte/setup/Index.svelte +++ b/front/js/svelte/setup/Index.svelte @@ -1,12 +1,20 @@
-{#each steps as step} - -{/each} + {#each steps as step} + + {/each} + +
+ {#if allSuccess} + Create the first user + {/if} +
\ No newline at end of file diff --git a/front/sass/_datepicker.scss b/front/sass/_datepicker.scss new file mode 100644 index 0000000..36eb5ea --- /dev/null +++ b/front/sass/_datepicker.scss @@ -0,0 +1,43 @@ + +.flatpickr-wrapper { + display: block !important; +} + +.editor-field { + .flatpickr-calendar { + border-radius: 12px !important; + } + + .flatpickr-months .flatpickr-month { + background: var(--p30); + color: var(--text); + font-size: 12px; + } + + .flatpickr-current-month .flatpickr-monthDropdown-months { + background: var(--p30); + } + + .flatpickr-weekdays{ + background: var(--p30); + color: var(--text); + + } + + .flatpickr-weekdaycontainer .flatpickr-weekday{ + background: var(--p30); + color: var(--text); + } + + .flatpickr-days{ + background: var(--p10); + color: var(--text); + } + + .flatpickr-time{ + background: var(--p10); + color: var(--text); + } + +} + diff --git a/front/sass/_dialog.scss b/front/sass/_dialog.scss index c4b6e26..d0f016e 100644 --- a/front/sass/_dialog.scss +++ b/front/sass/_dialog.scss @@ -15,7 +15,7 @@ body:has(dialog[open]) { dialog { margin: 2vh auto; - background-color: #fff; + background-color: var(--p10); padding: 34px; border: none; border-radius: 12px; @@ -49,6 +49,6 @@ dialog::backdrop { position: sticky; top: -34px; z-index: 999; - background: #fff; + background-color: var(--p10); padding: 10px 0; } \ No newline at end of file diff --git a/front/sass/app.scss b/front/sass/app.scss index 26a9c23..48ce6f4 100644 --- a/front/sass/app.scss +++ b/front/sass/app.scss @@ -70,6 +70,7 @@ @import "./reference-tags"; @import "./members"; @import "./revisions"; +@import "./datepicker"; body { background-color: var(--p10); @@ -104,7 +105,3 @@ a { .lucent-component { position: relative; } - -.flatpickr-wrapper { - display: block!important; -} \ No newline at end of file diff --git a/src/Commands/SetupDatabase.php b/src/Commands/SetupDatabase.php new file mode 100644 index 0000000..74bd602 --- /dev/null +++ b/src/Commands/SetupDatabase.php @@ -0,0 +1,105 @@ +tableUsers(); + $this->tableRecords(); + $this->tableRevisions(); + $this->tableSessions(); + $this->tableCommandLogs(); + + $this->info("Lucent Database Setup Completed"); + } + + private function tableUsers(): void + { + Schema::create('users', function (Blueprint $table) { + $table->uuid("id")->primary(); + $table->string('name')->nullable(); + $table->string('email')->unique(); + $table->jsonb('roles'); + $table->string('createdAt'); + $table->string('updatedAt'); + $table->string('loggedInAt'); + $table->string('mailToken')->nullable(); + + }); + } + + private function tableSessions(): void + { + Schema::create('sessions', function (Blueprint $table) { + $table->string('id')->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->string('ip_address', 45)->nullable(); + $table->text('user_agent')->nullable(); + $table->longText('payload'); + $table->integer('last_activity')->index(); + }); + } + + private function tableRecords(): void + { + Schema::create('records', function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->string('schema'); + $table->string('status'); + $table->jsonb('data'); + $table->jsonb('_sys'); + $table->jsonb('_file'); + $table->text('search')->default(""); + + $table->index(['schema', '_sys->updatedAt', 'status']); + $table->index('search'); + }); + + Schema::create('edges', function (Blueprint $table) { + $table->uuid('source'); + $table->uuid('target'); + $table->string('sourceSchema'); + $table->string('targetSchema'); + $table->string('field'); + $table->string('rank'); + + $table->unique(['source', 'target', "field"]); + }); + } + + private function tableRevisions(): void + { + Schema::create('revisions', function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->uuid('recordId'); + $table->string('schema'); + $table->jsonb('data'); + $table->jsonb('_sys'); + $table->jsonb('_file'); + $table->jsonb('_edges'); + }); + } + + private function tableCommandLogs(): void + { + Schema::create('command_logs', function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->string('signature'); + $table->integer('pid')->nullable(); + $table->text('logs'); + }); + } + +} diff --git a/src/Database/migrations/0000_create_users_table.php b/src/Database/migrations/0000_create_users_table.php deleted file mode 100644 index 3e241a4..0000000 --- a/src/Database/migrations/0000_create_users_table.php +++ /dev/null @@ -1,40 +0,0 @@ -uuid("id")->primary(); - $table->string('name')->nullable(); - $table->string('email')->unique(); - $table->jsonb('roles'); - $table->string('createdAt'); - $table->string('updatedAt'); - $table->string('loggedInAt'); - $table->string('mailToken')->nullable(); - - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('users'); - } -}; diff --git a/src/Database/migrations/0001_create_sessions_table.php b/src/Database/migrations/0001_create_sessions_table.php deleted file mode 100644 index ad4fe4d..0000000 --- a/src/Database/migrations/0001_create_sessions_table.php +++ /dev/null @@ -1,37 +0,0 @@ -string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); - $table->string('ip_address', 45)->nullable(); - $table->text('user_agent')->nullable(); - $table->longText('payload'); - $table->integer('last_activity')->index(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('sessions'); - } -}; diff --git a/src/Database/migrations/0002_records.php b/src/Database/migrations/0002_records.php deleted file mode 100644 index 07d2cda..0000000 --- a/src/Database/migrations/0002_records.php +++ /dev/null @@ -1,50 +0,0 @@ -uuid('id')->primary(); - $table->string('schema'); - $table->string('status'); - $table->jsonb('data'); - $table->jsonb('_sys'); - $table->jsonb('_file'); - - $table->index(['schema', 'status']); - }); - - Schema::create('edges', function (Blueprint $table) { - $table->uuid('source'); - $table->uuid('target'); - $table->string('sourceSchema'); - $table->string('targetSchema'); - $table->string('field'); - $table->string('rank'); - - $table->unique(['source', 'target', "field"]); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('records'); - Schema::dropIfExists('edges'); - } -}; diff --git a/src/Database/migrations/0003_revisions.php b/src/Database/migrations/0003_revisions.php deleted file mode 100644 index 88522f7..0000000 --- a/src/Database/migrations/0003_revisions.php +++ /dev/null @@ -1,37 +0,0 @@ -uuid('id')->primary(); - $table->uuid('recordId'); - $table->string('schema'); - $table->jsonb('data'); - $table->jsonb('_sys'); - $table->jsonb('_file'); - $table->jsonb('_edges'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('revisions'); - } -}; diff --git a/src/Database/migrations/0004_generatedIndexColumn.php b/src/Database/migrations/0004_generatedIndexColumn.php deleted file mode 100644 index 11de904..0000000 --- a/src/Database/migrations/0004_generatedIndexColumn.php +++ /dev/null @@ -1,38 +0,0 @@ -text('search')->default(""); - $table->index('search'); - }); - - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('records', function (Blueprint $table) { - $table->dropColumn('search'); - $table->dropIndex('search'); - }); - } -}; diff --git a/src/Database/migrations/0005_RecordsUpdatedIndex.php b/src/Database/migrations/0005_RecordsUpdatedIndex.php deleted file mode 100644 index cd73c55..0000000 --- a/src/Database/migrations/0005_RecordsUpdatedIndex.php +++ /dev/null @@ -1,37 +0,0 @@ -dropIndex(['schema', 'status']); - $table->index(['schema', '_sys->updatedAt', 'status']); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('records', function (Blueprint $table) { - - $table->dropIndex(['schema', '_sys->updatedAt', 'status']); - $table->index(['schema', 'status']); - }); - } -}; diff --git a/src/Database/migrations/0006_CommandLogs.php b/src/Database/migrations/0006_CommandLogs.php deleted file mode 100644 index d92a602..0000000 --- a/src/Database/migrations/0006_CommandLogs.php +++ /dev/null @@ -1,35 +0,0 @@ -uuid('id')->primary(); - $table->string('signature'); - $table->integer('pid')->nullable(); - $table->text('logs'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('command_logs'); - } -}; diff --git a/src/Http/Controller/SetupController.php b/src/Http/Controller/SetupController.php index 839e86f..b9d4dd0 100644 --- a/src/Http/Controller/SetupController.php +++ b/src/Http/Controller/SetupController.php @@ -3,7 +3,6 @@ namespace Lucent\Http\Controller; use App\Http\Controllers\Controller; -use Illuminate\Contracts\Session\Session; use Illuminate\Contracts\View\View; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -12,10 +11,15 @@ use Lucent\Account\AccountService; use Lucent\Channel\ChannelService; use Lucent\LucentException; use Lucent\Setup\Data\SetupStep; +use Lucent\Setup\Data\SetupStepStatus; use Lucent\Setup\Setup; use Lucent\Setup\Step\ComposerStep; +use Lucent\Setup\Step\DatabaseSetupStep; use Lucent\Setup\Step\IStep; +use Lucent\Setup\Step\LaravelEnvStep; use Lucent\Setup\Step\LucentConfigStep; +use Lucent\Setup\Step\StorageLinkSetupStep; +use Lucent\Setup\Step\StorageSetupStep; use Lucent\Svelte\Svelte; use function Lucent\Response\fail; use function Lucent\Response\ok; @@ -27,7 +31,6 @@ class SetupController private readonly AccountService $accountService, private readonly ChannelService $channelService, private readonly Svelte $svelte, - private readonly Setup $setup, ) { @@ -35,44 +38,35 @@ class SetupController public function setup(Request $request): View|RedirectResponse { - if ($this->accountService->countUsers() > 0) { - return redirect($this->channelService->channel->lucentUrl . "/login"); - } + $steps = array_reduce([ - new ComposerStep, - new LucentConfigStep, - ],fn(array $carry, IStep $setupStep)=> array_merge($carry,[$setupStep()]) ,[]); + new ComposerStep, + new LucentConfigStep, + new LaravelEnvStep, + new StorageSetupStep, + new StorageLinkSetupStep, + new DatabaseSetupStep, + ], fn(array $carry, IStep $setupStep) => array_merge($carry, [$setupStep()]), []); + $allSuccess = array_reduce($steps, fn(bool $carry, SetupStep $step) => !$carry ? false : $step->status === SetupStepStatus::SUCCESS, true); + + if($allSuccess){ + if ($this->accountService->countUsers() > 0) { + return redirect($this->channelService->channel->lucentUrl . "/login"); + } + } return $this->svelte->render( layout: "account", view: "setup", title: "Setup Lucent", data: [ - "steps" => $steps + "steps" => $steps, + "allSuccess" => $allSuccess, ] ); } - public function postRegister(Request $request): Response - { - - if ($this->accountService->countUsers() > 0) { - abort(400); - } - - try { - $this->authService->registerAdmin( - name: $request->input("name"), - email: $request->input("email"), - ); - } catch (LucentException $th) { - return fail($th); - } - - return ok(); - } - } diff --git a/src/Http/web.php b/src/Http/web.php index 51635b9..b71e12b 100644 --- a/src/Http/web.php +++ b/src/Http/web.php @@ -13,14 +13,18 @@ use Lucent\Http\Controller\RevisionController; use Lucent\Http\Controller\SetupController; +Route::get('/lucent/setup', [SetupController::class, 'setup']); + Route::group([ 'middleware' => ['web'], 'prefix' => "lucent" ], function () { + + Route::middleware(['lucent.guest'])->group(function () { Route::get('/', [AuthController::class, 'login']); - Route::get('/setup', [SetupController::class, 'setup']); + Route::get('/register', [AuthController::class, 'register']); Route::post('/register', [AuthController::class, 'postRegister']); Route::get('/login', [AuthController::class, 'login']); diff --git a/src/LucentServiceProvider.php b/src/LucentServiceProvider.php index 51399b2..f3884cb 100644 --- a/src/LucentServiceProvider.php +++ b/src/LucentServiceProvider.php @@ -12,6 +12,7 @@ use Lucent\Commands\CompileSchemas; use Lucent\Commands\LiveLink; use Lucent\Commands\RebuildThumbnails; use Lucent\Commands\RemoveOrphanEdges; +use Lucent\Commands\SetupDatabase; use Lucent\File\FileService; use Lucent\File\ImageService; use Lucent\Query\DatabaseGraph\DatabaseGraph; @@ -67,14 +68,13 @@ class LucentServiceProvider extends ServiceProvider $this->loadRoutesFrom(__DIR__ . '/Http/web.php'); $this->loadRoutesFrom(__DIR__ . '/Http/api.php'); - $this->loadMigrationsFrom(__DIR__ . '/Database/migrations'); - if ($this->app->runningInConsole()) { $this->commands([ CompileSchemas::class, RebuildThumbnails::class, LiveLink::class, RemoveOrphanEdges::class, + SetupDatabase::class, ]); } diff --git a/src/Setup/Setup.php b/src/Setup/Setup.php deleted file mode 100644 index fbae18f..0000000 --- a/src/Setup/Setup.php +++ /dev/null @@ -1,13 +0,0 @@ - [ + 'lucentdb' => [ + 'driver' => 'sqlite', + 'url' => env('LUCENT_DATABASE_URL'), + 'database' => env('LUCENT_DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + ], +EOD; + return SetupStep::makeFail($name, $instructions); + } + + try { + DB::connection("lucentdb")->table("records")->get(); + }catch (QueryException $e) { + $instructions = <<getSchemeAndHttpHost()) { + true => SetupStep::makeSuccess($name, $instructions), + false => SetupStep::makeFail($name, $instructions), + }; + } +} \ No newline at end of file diff --git a/src/Setup/Step/LucentConfigStep.php b/src/Setup/Step/LucentConfigStep.php index 88766dc..79f2bdb 100644 --- a/src/Setup/Step/LucentConfigStep.php +++ b/src/Setup/Step/LucentConfigStep.php @@ -10,14 +10,14 @@ class LucentConfigStep implements IStep public function __invoke(): SetupStep { - $lucentConfig = config("lucent.schemasPath"); + $lucentConfig = config("lucent.schemas_path"); $name = "Generate Lucent config"; $instructions = << !$carry ? false : is_link($link) , true); + + return match ($allLinksExist) { + true => SetupStep::makeSuccess($name, $instructions), + false => SetupStep::makeFail($name, $instructions), + }; + } +} \ No newline at end of file diff --git a/src/Setup/Step/StorageSetupStep.php b/src/Setup/Step/StorageSetupStep.php new file mode 100644 index 0000000..0206ad7 --- /dev/null +++ b/src/Setup/Step/StorageSetupStep.php @@ -0,0 +1,42 @@ + [ + 'lucent' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => true, + ], + ], +]; + + +EOD; + + + return match (!empty($storage)) { + true => SetupStep::makeSuccess($name, $instructions), + false => SetupStep::makeFail($name, $instructions), + }; + } +} \ No newline at end of file