diff --git a/front/public/js/editor.js b/front/public/js/editor.js
new file mode 100644
index 0000000..471e05a
--- /dev/null
+++ b/front/public/js/editor.js
@@ -0,0 +1,5 @@
+document.addEventListener("DOMContentLoaded", onReady);
+
+function onReady(){
+ console.log("ready yo")
+}
\ No newline at end of file
diff --git a/front/views/layouts/channel.blade.php b/front/views/layouts/channel.blade.php
index 03659a6..5b4d5e9 100644
--- a/front/views/layouts/channel.blade.php
+++ b/front/views/layouts/channel.blade.php
@@ -6,6 +6,7 @@
@yield('title') - {{ config("lucent.name") }}
@include("lucent::includes.assets")
+ @stack("scripts")
diff --git a/front/views/new/edit/edit.blade.php b/front/views/new/edit/edit.blade.php
new file mode 100644
index 0000000..08b338f
--- /dev/null
+++ b/front/views/new/edit/edit.blade.php
@@ -0,0 +1,25 @@
+@extends("lucent::layouts.channel")
+@pushonce("scripts")
+
+@endpushonce
+@section("title")
+ Edit Record
+@endsection
+@section("content")
+
+
+
+ @foreach($schema->groups as $group)
+ {{$group}}
+ @foreach($schema->fields as $field)
+ @php
+ $fieldId = "field-".$field->data->name."-".$record->id;
+ @endphp
+
+ @include("lucent::new.edit.field-header" ,["id" => $fieldId])
+ {!! $field->renderForm($record, $fieldId) !!}
+
+ @endforeach
+
+ @endforeach
+@endsection
\ No newline at end of file
diff --git a/front/views/new/edit/field-header.blade.php b/front/views/new/edit/field-header.blade.php
new file mode 100644
index 0000000..9749610
--- /dev/null
+++ b/front/views/new/edit/field-header.blade.php
@@ -0,0 +1,11 @@
+
diff --git a/front/views/new/edit/fields/file.blade.php b/front/views/new/edit/fields/file.blade.php
new file mode 100644
index 0000000..788b5e1
--- /dev/null
+++ b/front/views/new/edit/fields/file.blade.php
@@ -0,0 +1,8 @@
+@pushonce("scripts")
+
+@endpushonce
+
+
+yo
\ No newline at end of file
diff --git a/front/views/new/edit/fields/reference.blade.php b/front/views/new/edit/fields/reference.blade.php
new file mode 100644
index 0000000..788b5e1
--- /dev/null
+++ b/front/views/new/edit/fields/reference.blade.php
@@ -0,0 +1,8 @@
+@pushonce("scripts")
+
+@endpushonce
+
+
+yo
\ No newline at end of file
diff --git a/front/views/new/edit/fields/rich.blade.php b/front/views/new/edit/fields/rich.blade.php
new file mode 100644
index 0000000..788b5e1
--- /dev/null
+++ b/front/views/new/edit/fields/rich.blade.php
@@ -0,0 +1,8 @@
+@pushonce("scripts")
+
+@endpushonce
+
+
+yo
\ No newline at end of file
diff --git a/front/views/new/edit/fields/slug.blade.php b/front/views/new/edit/fields/slug.blade.php
new file mode 100644
index 0000000..788b5e1
--- /dev/null
+++ b/front/views/new/edit/fields/slug.blade.php
@@ -0,0 +1,8 @@
+@pushonce("scripts")
+
+@endpushonce
+
+
+yo
\ No newline at end of file
diff --git a/front/views/new/edit/fields/text.blade.php b/front/views/new/edit/fields/text.blade.php
new file mode 100644
index 0000000..c0baa71
--- /dev/null
+++ b/front/views/new/edit/fields/text.blade.php
@@ -0,0 +1,15 @@
+@pushonce("scripts")
+
+@endpushonce
+
+
+
\ No newline at end of file
diff --git a/src/Channel/ChannelService.php b/src/Channel/ChannelService.php
index 0f16dbf..dbe1bac 100644
--- a/src/Channel/ChannelService.php
+++ b/src/Channel/ChannelService.php
@@ -3,41 +3,45 @@
namespace Lucent\Channel;
-use DirectoryIterator;
-use Illuminate\Support\Str;
-use Intervention\Image\Drivers\Imagick\Encoders\WebpEncoder;
+use Illuminate\Foundation\Application;
use Lucent\Channel\Data\UserCommand;
+use Lucent\Field\Field;
+use Lucent\LucentException;
use Lucent\Primitive\Collection;
+use Lucent\Schema\CollectionSchema;
+use Lucent\Schema\FieldInterface;
+use Lucent\Schema\FilesSchema;
use Lucent\Schema\Schema;
-use Lucent\Schema\SchemaService;
+use Lucent\Schema\SingletonSchema;
use PhpOption\Option;
final class ChannelService
{
public Channel $channel;
+ /**
+ * @var class-string[]
+ */
+ public array $fields = [];
- private function __construct(
- public SchemaService $schemaService,
- )
+ public function __construct(public Application $app)
{
}
- public static function fromConfig(): ChannelService
+ public function load(): void
{
$schemasArray = [];
if (file_exists(schemas_path())) {
$schemasJson = file_get_contents(schemas_path());
$schemasArray = json_decode($schemasJson, true);
}
- $schemaService = new SchemaService();
- $schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map([$schemaService, 'fromArray']);
+
+ $schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map($this->makeSchemafromArray(...));
$userCommands = [];
foreach (config("lucent.commands") ?? [] as $signature => $desc) {
$userCommands[] = new UserCommand($desc, $signature);
}
-
$channel = new Channel(
name: config("lucent.name") ?? "",
url: rtrim(config("lucent.url") ?? "", "/"),
@@ -48,9 +52,7 @@ final class ChannelService
roles: $schemasArray["roles"] ?? []
);
- $channelService = new ChannelService($schemaService);
- $channelService->channel = $channel;
- return $channelService;
+ $this->channel = $channel;
}
/**
@@ -90,4 +92,81 @@ final class ChannelService
return $schemasAllRead->merge($schemasCanWrite)->unique()->values()->toArray();
}
+ /**
+ * @param class-string[] $fields
+ * @return void
+ */
+ public function registerFields(array $fields): void
+ {
+ $this->fields = array_merge($this->fields, $fields);
+ }
+
+ public function makeSchemafromArray(array $schemaArr): Schema
+ {
+
+ return match ($schemaArr["type"]) {
+ "collection" => new CollectionSchema(
+ name: $schemaArr["name"],
+ label: $schemaArr["label"],
+ visible: $schemaArr["visible"] ?? [],
+ groups: $schemaArr["groups"] ?? [],
+ fields: (new Collection($schemaArr["fields"]))->map($this->mapFields(...)),
+ folder: $schemaArr["folder"] ?? "",
+ color: $schemaArr["color"] ?? "",
+ sortBy: $schemaArr["sortBy"] ?? "-_sys.updatedAt",
+ cardTitle: $schemaArr["titleTemplate"] ?? $schemaArr["cardTitle"] ?? null,
+ cardImage: $schemaArr["cardImage"] ?? null,
+ revisions: $schemaArr["revisions"] ?? 0,
+ read: $schemaArr["read"] ?? [],
+ write: $schemaArr["write"] ?? [],
+ ),
+ "singleton" => new SingletonSchema(
+ name: $schemaArr["name"],
+ label: $schemaArr["label"],
+ groups: $schemaArr["groups"] ?? [],
+ fields: (new Collection($schemaArr["fields"]))->map($this->mapFields(...)),
+ folder: $schemaArr["folder"] ?? "",
+ color: $schemaArr["color"] ?? "",
+ cardTitle: $schemaArr["titleTemplate"] ?? $schemaArr["cardTitle"] ?? null,
+ cardImage: $schemaArr["cardImage"] ?? null,
+ revisions: $schemaArr["revisions"] ?? 0,
+ read: $schemaArr["read"] ?? [],
+ write: $schemaArr["write"] ?? [],
+ ),
+ "files" => new FilesSchema(
+ name: $schemaArr["name"],
+ label: $schemaArr["label"],
+ fields: (new Collection($schemaArr["fields"]))->map($this->mapFields(...)),
+ disk: $schemaArr["disk"] ?? "lucent",
+ path: $schemaArr["path"] ?? $schemaArr["name"],
+ groups: $schemaArr["groups"] ?? [],
+ folder: $schemaArr["folder"] ?? "",
+ sortBy: $schemaArr["sortBy"] ?? "-_sys.updatedAt",
+ color: $schemaArr["color"] ?? "",
+ cardTitle: $schemaArr["titleTemplate"] ?? $schemaArr["cardTitle"] ?? null,
+ cardImage: $schemaArr["cardImage"] ?? null,
+ revisions: $schemaArr["revisions"] ?? 0,
+ read: $schemaArr["read"] ?? [],
+ write: $schemaArr["write"] ?? [],
+ )
+ };
+
+ }
+
+ public function mapFields(array $field): Field
+ {
+ $uiClass = collect($this->fields)
+ ->filter(fn($className) => str_ends_with(strtolower($className), strtolower($field["ui"])))
+ ->first();
+
+ if (empty($uiClass)) {
+ throw new LucentException("Field UI " . $field["ui"] . " not found");
+ }
+
+
+ $ui = $this->app->make($uiClass);
+ $ui->setData($field);
+ return $ui;
+ }
+
}
diff --git a/src/Field/Field.php b/src/Field/Field.php
new file mode 100644
index 0000000..1935149
--- /dev/null
+++ b/src/Field/Field.php
@@ -0,0 +1,11 @@
+info = new FieldInfo("file", "File", FieldType::FILE);
+ }
+
+ public function setData(array $data): void
+ {
+ $this->data = Data::fromArray($data);
+ }
+
+ public function format(RecordData $input, RecordData $output): RecordData
+ {
+ return $output;
+ }
+
+ public function renderForm(): string
+ {
+ return view('lucent::new.edit.fields.file', ["info" => $this->info, "data" => $this->data])->render();;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/Field/Reference/Data.php b/src/Field/Reference/Data.php
new file mode 100644
index 0000000..ad7bf9e
--- /dev/null
+++ b/src/Field/Reference/Data.php
@@ -0,0 +1,38 @@
+info = new FieldInfo("reference", "Reference", FieldType::REFERENCE);
+ }
+
+ public function setData(array $data): void
+ {
+ $this->data = Data::fromArray($data);
+ }
+
+ public function format(RecordData $input, RecordData $output): RecordData
+ {
+ return $output;
+ }
+
+ public function renderForm(): string
+ {
+ return view('lucent::new.edit.fields.reference', ["info" => $this->info, "data" => $this->data])->render();;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Field/Rich/Data.php b/src/Field/Rich/Data.php
new file mode 100644
index 0000000..43af408
--- /dev/null
+++ b/src/Field/Rich/Data.php
@@ -0,0 +1,40 @@
+info = new FieldInfo("rich", "Rich Editor", FieldType::STRING);
+ }
+
+ public function setData(array $data): void
+ {
+ $this->data = Data::fromArray($data);
+ }
+
+ public function format(RecordData $input, RecordData $output): RecordData
+ {
+ $value = $input[$this->data->name] ?? null;
+ $output[$this->data->name] = (new Nullable($this->data->nullable, $value, ""))->value();
+ return $output;
+ }
+
+ public function renderForm(): string
+ {
+ return view('lucent::new.edit.fields.rich', ["info" => $this->info, "data" => $this->data])->render();;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Field/Slug/Data.php b/src/Field/Slug/Data.php
new file mode 100644
index 0000000..d761f2d
--- /dev/null
+++ b/src/Field/Slug/Data.php
@@ -0,0 +1,41 @@
+info = new FieldInfo("slug", "Slug", FieldType::STRING);
+ }
+
+ public function setData(array $data): void
+ {
+ $this->data = Data::fromArray($data);
+ }
+
+ public function format(RecordData $input, RecordData $output): RecordData
+ {
+ $value = !empty($input[$this->data->name]) ? (string)$input[$this->data->name] : null;
+ if(empty($value)){
+ $value = Str::slug($input[$this->data->source]);
+ }
+
+ $output[$this->data->name] = (new Nullable($this->data->nullable, $value, ""))->value();
+ return $output;
+ }
+
+ public function renderForm(): string
+ {
+ return view('lucent::new.edit.fields.slug', ["info" => $this->info, "data" => $this->data])->render();;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Field/Text/Data.php b/src/Field/Text/Data.php
new file mode 100644
index 0000000..a892189
--- /dev/null
+++ b/src/Field/Text/Data.php
@@ -0,0 +1,41 @@
+info = new FieldInfo("text", "Text", FieldType::STRING);
+ }
+
+ public function setData(array $data): void
+ {
+ $this->data = Data::fromArray($data);
+ }
+
+
+ public function format(RecordData $input, RecordData $output): RecordData
+ {
+ $value = !empty($input[$this->data->name]) ? (string)$input[$this->data->name] : null;
+ $output[$this->data->name] = (new Nullable($this->data->nullable, $value, ""))->value();
+ return $output;
+ }
+
+ public function renderForm($record, string $fieldId): string
+ {
+ return view('lucent::new.edit.fields.text', ["info" => $this->info, "data" => $this->data , "record" => $record, "fieldId" => $fieldId])->render();
+ }
+}
\ No newline at end of file
diff --git a/src/Http/Controller/RecordController.php b/src/Http/Controller/RecordController.php
index 043b16d..679803c 100644
--- a/src/Http/Controller/RecordController.php
+++ b/src/Http/Controller/RecordController.php
@@ -233,6 +233,49 @@ class RecordController extends Controller
$record = $graph->records->first();
+ if (!in_array($record->schema, $this->accountService->currentReadableSchemas())) {
+ return $this->svelte->render(
+ layout: "channel",
+ view: "recordNotFound",
+ title: "Schema Not Found",
+ );
+ }
+
+ $schema = $this->channelService->getSchema($record->schema)->get();
+
+ return view("lucent::new.edit.edit",[
+ "schema" => $schema,
+ "graph" => $graph,
+ "record" => $record,
+ "users" => $this->accountService->all(),
+ "isWritable" => in_array($record->schema, $this->accountService->currentWritableSchemas())
+ ]);
+ }
+
+ public function _edit(Request $request)
+ {
+ $rid = $request->route("rid");
+
+ $graph = $this->query
+ ->filter(["id" => $rid])
+ ->limit(1)
+ ->skip(0)
+ ->childrenDepth(2)
+ ->childrenLimit(200)
+ ->parentsDepth(1)
+ ->parentsLimit(200)
+ ->run();
+
+ if ($graph->records->isEmpty()) {
+ return $this->svelte->render(
+ layout: "channel",
+ view: "recordNotFound",
+ title: "Record Not Found",
+ );
+ }
+
+ $record = $graph->records->first();
+
if (!in_array($record->schema, $this->accountService->currentReadableSchemas())) {
return $this->svelte->render(
diff --git a/src/LucentServiceProvider.php b/src/LucentServiceProvider.php
index 312acc0..9957497 100644
--- a/src/LucentServiceProvider.php
+++ b/src/LucentServiceProvider.php
@@ -22,6 +22,11 @@ use Lucent\Commands\RemoveOrphanRecords;
use Lucent\Commands\Setup;
use Lucent\Commands\SetupDatabase;
use Lucent\Commands\UpgradeFiles122;
+use Lucent\Field\File\File;
+use Lucent\Field\Reference\Reference;
+use Lucent\Field\Rich\Rich;
+use Lucent\Field\Slug\Slug;
+use Lucent\Field\Text\Text;
use Lucent\File\FileService;
use Lucent\Hook\HookService;
use Lucent\Query\DatabaseGraph\DatabaseGraph;
@@ -29,7 +34,6 @@ use Lucent\Query\DatabaseGraph\PgsqlDatabaseGraph;
use Lucent\Query\DatabaseGraph\SqliteDatabaseGraph;
use Lucent\Record\Event\RecordCreated;
use Lucent\Record\Event\RecordUpdated;
-use Lucent\Record\Record;
use Lucent\Revision\Listener\CreateRevision;
class LucentServiceProvider extends ServiceProvider
@@ -40,9 +44,10 @@ class LucentServiceProvider extends ServiceProvider
public function register(): void
{
$this->app->singleton(ChannelService::class, function (Application $application) {
- return ChannelService::fromConfig();
+ return new ChannelService($application);
});
+
$this->app->singleton(HookService::class, function (Application $application) {
return new HookService;
});
@@ -69,7 +74,7 @@ class LucentServiceProvider extends ServiceProvider
/**
* Bootstrap any package services.
*/
- public function boot(Router $router): void
+ public function boot(Router $router, ChannelService $channelService): void
{
$manifestPath = public_path('vendor/lucent/dist/manifest.json');
@@ -102,6 +107,16 @@ class LucentServiceProvider extends ServiceProvider
]);
}
+ $channelService->registerFields([
+ Text::class,
+ Slug::class,
+ Rich::class,
+ File::class,
+ Reference::class,
+ ]);
+
+ $channelService->load();
+
View::share('manifest', $manifest);
View::share('file', app()->make(FileService::class));
Blade::anonymousComponentPath(__DIR__ . '../front/views/components', "lucent");
diff --git a/src/Record/InputFormatter.php b/src/Record/InputFormatter.php
index 1975f4f..e1af526 100644
--- a/src/Record/InputFormatter.php
+++ b/src/Record/InputFormatter.php
@@ -3,6 +3,7 @@
namespace Lucent\Record;
use Lucent\Channel\ChannelService;
+use Lucent\Field\Field;
use Lucent\Schema\FieldInterface;
class InputFormatter
@@ -16,12 +17,8 @@ class InputFormatter
public function fill(string $schemaName, RecordData $input): RecordData
{
-
$schema = $this->channelService->getSchema($schemaName)->get();
-
- $data = $schema->fields->reduce(fn(array $carry, FieldInterface $field) => $field->format($input->toArray(), $carry), []);
-
- return new RecordData($data);
+ return $schema->fields->reduce(fn(RecordData $carry, Field $field) => $field->format($input, $carry), new RecordData([]));
}
diff --git a/src/Record/RecordData.php b/src/Record/RecordData.php
index eade6a4..6867bbd 100644
--- a/src/Record/RecordData.php
+++ b/src/Record/RecordData.php
@@ -7,7 +7,6 @@ use Lucent\ArrayContainer;
class RecordData extends ArrayContainer
{
-
public function merge(RecordData $data): RecordData
{
diff --git a/src/Schema/CollectionSchema.php b/src/Schema/CollectionSchema.php
index e9f09d6..1d406d6 100644
--- a/src/Schema/CollectionSchema.php
+++ b/src/Schema/CollectionSchema.php
@@ -2,6 +2,7 @@
namespace Lucent\Schema;
+use Lucent\Field\Field;
use Lucent\Primitive\Collection;
class CollectionSchema implements Schema
@@ -9,7 +10,7 @@ class CollectionSchema implements Schema
public Type $type = Type::COLLECTION;
/**
- * @param Collection $fields
+ * @param Collection $fields
* @param array $visible
*/
function __construct(
diff --git a/src/Schema/FieldInfo.php b/src/Schema/FieldInfo.php
index 52c1cd1..a923bfd 100644
--- a/src/Schema/FieldInfo.php
+++ b/src/Schema/FieldInfo.php
@@ -1,12 +1,10 @@
$fields
+ * @param Collection $fields
* @param array $groups
*/
function __construct(
diff --git a/src/Schema/SchemaService.php b/src/Schema/SchemaService.php
index 371625a..29f0c93 100644
--- a/src/Schema/SchemaService.php
+++ b/src/Schema/SchemaService.php
@@ -13,86 +13,6 @@ class SchemaService
{
}
- public function fromArray(array $schemaArr): Schema
- {
- return match ($schemaArr["type"]) {
- "collection" => new CollectionSchema(
- name: $schemaArr["name"],
- label: $schemaArr["label"],
- visible: $schemaArr["visible"] ?? [],
- groups: $schemaArr["groups"] ?? [],
- fields: (new Collection($schemaArr["fields"]))->map([$this, 'mapFields']),
- folder: $schemaArr["folder"] ?? "",
- color: $schemaArr["color"] ?? "",
- sortBy: $schemaArr["sortBy"] ?? "-_sys.updatedAt",
- cardTitle: $schemaArr["titleTemplate"] ?? $schemaArr["cardTitle"] ?? null,
- cardImage: $schemaArr["cardImage"] ?? null,
- revisions: $schemaArr["revisions"] ?? 0,
- read: $schemaArr["read"] ?? [],
- write: $schemaArr["write"] ?? [],
- ),
- "singleton" => new SingletonSchema(
- name: $schemaArr["name"],
- label: $schemaArr["label"],
- groups: $schemaArr["groups"] ?? [],
- fields: (new Collection($schemaArr["fields"]))->map([$this, 'mapFields']),
- folder: $schemaArr["folder"] ?? "",
- color: $schemaArr["color"] ?? "",
- cardTitle: $schemaArr["titleTemplate"] ?? $schemaArr["cardTitle"] ?? null,
- cardImage: $schemaArr["cardImage"] ?? null,
- revisions: $schemaArr["revisions"] ?? 0,
- read: $schemaArr["read"] ?? [],
- write: $schemaArr["write"] ?? [],
- ),
- "files" => new FilesSchema(
- name: $schemaArr["name"],
- label: $schemaArr["label"],
- fields: (new Collection($schemaArr["fields"]))->map([$this, 'mapFields']),
- disk: $schemaArr["disk"] ?? "lucent",
- path: $schemaArr["path"] ?? $schemaArr["name"],
- groups: $schemaArr["groups"] ?? [],
- folder: $schemaArr["folder"] ?? "",
- sortBy: $schemaArr["sortBy"] ?? "-_sys.updatedAt",
- color: $schemaArr["color"] ?? "",
- cardTitle: $schemaArr["titleTemplate"] ?? $schemaArr["cardTitle"] ?? null,
- cardImage: $schemaArr["cardImage"] ?? null,
- revisions: $schemaArr["revisions"] ?? 0,
- read: $schemaArr["read"] ?? [],
- write: $schemaArr["write"] ?? [],
- )
- };
-
- }
-
- public function mapFields(array $field): FieldInterface
- {
-
- $schemaFields = [
- \Lucent\Schema\Ui\Checkbox::class,
- \Lucent\Schema\Ui\Color::class,
- \Lucent\Schema\Ui\Date::class,
- \Lucent\Schema\Ui\Datetime::class,
- \Lucent\Schema\Ui\File::class,
- \Lucent\Schema\Ui\Json::class,
- \Lucent\Schema\Ui\Markdown::class,
- \Lucent\Schema\Ui\Number::class,
- \Lucent\Schema\Ui\Reference::class,
- \Lucent\Schema\Ui\Rich::class,
- \Lucent\Schema\Ui\Slug::class,
- \Lucent\Schema\Ui\Text::class,
- \Lucent\Schema\Ui\Textarea::class,
- ];
- $ui = collect($schemaFields)->filter(function ($className) use ($field) {
- return str_ends_with(strtolower($className), "\\" . strtolower($field["ui"]));
- })->first();
-
- if (empty($ui)) {
- throw new LucentException("Field UI " . $field["ui"] . " not found");
- }
-
- unset($field["ui"]);
- return new $ui(...$field);
- }
}
diff --git a/src/Schema/SingletonSchema.php b/src/Schema/SingletonSchema.php
index 2f6cc99..935fef0 100644
--- a/src/Schema/SingletonSchema.php
+++ b/src/Schema/SingletonSchema.php
@@ -2,6 +2,7 @@
namespace Lucent\Schema;
+use Lucent\Field\Field;
use Lucent\Primitive\Collection;
class SingletonSchema implements Schema
@@ -9,7 +10,7 @@ class SingletonSchema implements Schema
public Type $type = Type::COLLECTION;
/**
- * @param Collection $fields
+ * @param Collection $fields
*/
function __construct(
public string $name,