field create
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
let app;
|
||||
let channel;
|
||||
|
||||
export function createApp(channelData) {
|
||||
channel = channelData;
|
||||
|
||||
app = {
|
||||
url: (path) => {
|
||||
return channel.lucentUrl + "/" + path;
|
||||
},
|
||||
};
|
||||
return app;
|
||||
}
|
||||
|
||||
export function getApp() {
|
||||
return app;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<script>
|
||||
import ChannelLayout from "../../layouts/ChannelLayout.svelte";
|
||||
import { post } from "../../modules/remote";
|
||||
import { getApp } from "../../app";
|
||||
let { channel, user, data } = $props();
|
||||
let name = $state("");
|
||||
let alias = $state("");
|
||||
const app = getApp();
|
||||
|
||||
function handleSchemaCreate(e) {
|
||||
e.preventDefault();
|
||||
console.log(data);
|
||||
post(
|
||||
app.url("fields"),
|
||||
{
|
||||
schemaId: data.schema.id,
|
||||
name: name,
|
||||
alias: alias,
|
||||
fieldType: data.type,
|
||||
},
|
||||
(data, err) => {
|
||||
if (err.isEmpty()) {
|
||||
Turbo.visit(app.url("fields/edit/" + data.field.id));
|
||||
} else {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<ChannelLayout {body} {channel} {user}></ChannelLayout>
|
||||
{#snippet body()}
|
||||
<h3 class="header-small mb-4 mt-5">Create a <em>{data.type}</em> field</h3>
|
||||
|
||||
<form onsubmit={handleSchemaCreate}>
|
||||
<fieldset>
|
||||
<label>
|
||||
Name
|
||||
<input
|
||||
bind:value={name}
|
||||
placeholder="ex. Description"
|
||||
minlength="2"
|
||||
maxlength="30"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
Alias
|
||||
<input
|
||||
bind:value={alias}
|
||||
placeholder="ex. description"
|
||||
minlength="2"
|
||||
maxlength="30"
|
||||
required
|
||||
aria-describedby="alias-helper"
|
||||
/>
|
||||
<small id="alias-helper">
|
||||
Developers will use this to reference the field
|
||||
</small>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<button type="submit">Create</button>
|
||||
</form>
|
||||
{/snippet}
|
||||
@@ -1,9 +1,11 @@
|
||||
<script>
|
||||
import ChannelLayout from "../../layouts/ChannelLayout.svelte";
|
||||
import { post } from "../../modules/remote";
|
||||
import { getApp } from "../../app";
|
||||
let { channel, user, data } = $props();
|
||||
let newSchemaName = $state("");
|
||||
let newSchemaAlias = $state("");
|
||||
const app = getApp();
|
||||
|
||||
function handleSchemaCreate(e) {
|
||||
e.preventDefault();
|
||||
@@ -15,7 +17,7 @@
|
||||
},
|
||||
(data, err) => {
|
||||
if (err.isEmpty()) {
|
||||
window.location.reload();
|
||||
Turbo.visit(window.location.href);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -79,8 +81,9 @@
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href={`/fields/create?schema=${schema.id}&type=text`}
|
||||
>Text</a
|
||||
href={app.url(
|
||||
`fields/create?schema=${schema.id}&type=text`,
|
||||
)}>Text</a
|
||||
>
|
||||
</li>
|
||||
|
||||
|
||||
+9
-6
@@ -1,7 +1,6 @@
|
||||
import { axiosInstance } from "./bootstrap";
|
||||
import { mount, setContext, unmount } from "svelte";
|
||||
|
||||
import * as Turbo from "@hotwired/turbo";
|
||||
// import "../sass/app.scss";
|
||||
import { mount, unmount } from "svelte";
|
||||
import "../css/app.css";
|
||||
import Register from "./svelte/account/Register.svelte";
|
||||
import Login from "./svelte/account/Login.svelte";
|
||||
@@ -14,7 +13,9 @@ import RecordEdit from "./svelte/records/Edit.svelte";
|
||||
import ContentIndex from "./svelte/content/Index.svelte";
|
||||
import HomeEntry from "./entry/HomeEntry/HomeEntry.svelte";
|
||||
import SchemaEntry from "./entry/SchemaEntry/SchemaEntry.svelte";
|
||||
import FieldCreateEntry from "./entry/FieldCreateEntry/FieldCreateEntry.svelte";
|
||||
import BuildReport from "./svelte/build/Report.svelte";
|
||||
import { createApp } from "./app";
|
||||
|
||||
const entryComponents = {
|
||||
members: Members,
|
||||
@@ -29,11 +30,14 @@ const entryComponents = {
|
||||
profile: Profile,
|
||||
setup: SetupIndex,
|
||||
schemas: SchemaEntry,
|
||||
fieldCreate: FieldCreateEntry,
|
||||
};
|
||||
Turbo.start();
|
||||
|
||||
let loadedComponents = [];
|
||||
|
||||
let loadSvelte = function () {
|
||||
Turbo.cache.clear();
|
||||
loadedComponents.map((comp) => unmount(comp));
|
||||
loadedComponents = [];
|
||||
|
||||
@@ -53,7 +57,7 @@ let loadSvelte = function () {
|
||||
return [];
|
||||
}
|
||||
// props.axios = axiosInstance;
|
||||
|
||||
createApp(props.channel);
|
||||
const compOptions = {
|
||||
target: element,
|
||||
props: props,
|
||||
@@ -62,5 +66,4 @@ let loadSvelte = function () {
|
||||
};
|
||||
Array.from(elements).map(loadElement);
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", loadSvelte);
|
||||
document.addEventListener("turbo:load", loadSvelte);
|
||||
|
||||
Generated
+12
@@ -4,6 +4,9 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@hotwired/turbo": "^8.0.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codemirror/commands": "^6.6.0",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
@@ -622,6 +625,15 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@hotwired/turbo": {
|
||||
"version": "8.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@hotwired/turbo/-/turbo-8.0.20.tgz",
|
||||
"integrity": "sha512-IilkH/+h92BRLeY/rMMR3MUh1gshIfdra/qZzp/Bl5FmiALD/6sQZK/ecxSbumeyOYiWr/JRI+Au1YQmkJGnoA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
|
||||
@@ -26,5 +26,8 @@
|
||||
"tinymce": "^6.8.4",
|
||||
"trix": "^2.1.5",
|
||||
"vite": "^7.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hotwired/turbo": "^8.0.20"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php namespace Lucent\Core\Repository;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Core\Schema\Data\Field;
|
||||
use Lucent\Core\Schema\FieldModule;
|
||||
use Lucent\Core\Schema\SchemaModule;
|
||||
|
||||
class FieldRepo
|
||||
{
|
||||
const TABLE_NAME = "fields";
|
||||
|
||||
/**
|
||||
* @@return Field[]
|
||||
*/
|
||||
public static function all(): array
|
||||
{
|
||||
return DB::table(self::TABLE_NAME)
|
||||
->orderBy("name")
|
||||
->get()
|
||||
->map(SchemaModule::fromDb(...))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function insert(Field $field): void
|
||||
{
|
||||
DB::table(self::TABLE_NAME)->insert(FieldModule::toDb($field));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php namespace Lucent\Core\Schema\Data;
|
||||
|
||||
use Lucent\Core\Schema\Data\FieldProp\IFieldProp;
|
||||
|
||||
class Field
|
||||
{
|
||||
public function __construct(
|
||||
@@ -7,5 +9,7 @@ class Field
|
||||
public string $alias,
|
||||
public string $name,
|
||||
public string $type,
|
||||
public string $schemaId,
|
||||
public IFieldProp $props,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php namespace Lucent\Core\Schema\Data\FieldProp;
|
||||
|
||||
class FieldProp
|
||||
{
|
||||
public static function fromType(string $type): IFieldProp
|
||||
{
|
||||
return match ($type) {
|
||||
"text" => new TextFieldProp(
|
||||
required: false,
|
||||
readonly: false,
|
||||
hidden: false,
|
||||
min: 0,
|
||||
max: 0,
|
||||
help: "",
|
||||
default: "",
|
||||
),
|
||||
default => new InvalidFieldProp(),
|
||||
};
|
||||
}
|
||||
|
||||
public static function fromDb(string $propsJson): IFieldProp
|
||||
{
|
||||
$props = json_decode($propsJson, true);
|
||||
return match ($props["type"]) {
|
||||
"text" => new TextFieldProp(
|
||||
required: $props["required"] ?? false,
|
||||
readonly: $props["readonly"] ?? false,
|
||||
hidden: $props["hidden"] ?? false,
|
||||
min: $props["min"] ?? 0,
|
||||
max: $props["max"] ?? 0,
|
||||
help: $props["help"] ?? "",
|
||||
default: $props["default"] ?? "",
|
||||
),
|
||||
default => new InvalidFieldProp(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php namespace Lucent\Core\Schema\Data\FieldProp;
|
||||
|
||||
interface IFieldProp {}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php namespace Lucent\Core\Schema\Data\FieldProp;
|
||||
|
||||
class InvalidFieldProp implements IFieldProp
|
||||
{
|
||||
public function __construct() {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php namespace Lucent\Core\Schema\Data\FieldProp;
|
||||
|
||||
class TextFieldProp implements IFieldProp
|
||||
{
|
||||
public function __construct(
|
||||
public bool $required,
|
||||
public bool $readonly,
|
||||
public bool $hidden,
|
||||
public string $default,
|
||||
public int $min,
|
||||
public int $max,
|
||||
public string $help,
|
||||
) {}
|
||||
}
|
||||
@@ -1,18 +1,20 @@
|
||||
<?php namespace Lucent\Core\Schema;
|
||||
|
||||
use Lucent\Core\Schema\Data\Field;
|
||||
use Lucent\Core\Schema\Data\FieldProp\FieldProp;
|
||||
use stdClass;
|
||||
|
||||
class FieldModule
|
||||
{
|
||||
public static function fromArray(array $data): Field
|
||||
{
|
||||
return new Field(
|
||||
id: $data["id"],
|
||||
alias: $data["alias"],
|
||||
name: $data["name"],
|
||||
type: $data["type"],
|
||||
);
|
||||
}
|
||||
// public static function fromArray(array $data): Field
|
||||
// {
|
||||
// return new Field(
|
||||
// id: $data["id"],
|
||||
// alias: $data["alias"],
|
||||
// name: $data["name"],
|
||||
// type: $data["type"],
|
||||
// );
|
||||
// }
|
||||
|
||||
public static function toDb(Field $field): array
|
||||
{
|
||||
@@ -21,6 +23,20 @@ class FieldModule
|
||||
"alias" => $field->alias,
|
||||
"name" => $field->name,
|
||||
"type" => $field->type,
|
||||
"props" => json_encode($field->props),
|
||||
"schema_id" => $field->schemaId,
|
||||
];
|
||||
}
|
||||
|
||||
public static function fromDb(stdClass $data): Field
|
||||
{
|
||||
return new Field(
|
||||
id: data_get($data, "id"),
|
||||
alias: data_get($data, "alias"),
|
||||
name: data_get($data, "name"),
|
||||
type: data_get($data, "type"),
|
||||
schemaId: data_get($data, "schema_id"),
|
||||
props: FieldProp::fromDb(data_get($data, "props")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Account\AccountService;
|
||||
use Lucent\Account\AuthService;
|
||||
use Lucent\Core\Repository\FieldRepo;
|
||||
use Lucent\Core\Repository\SchemaRepo;
|
||||
use Lucent\Core\Schema\Data\Field;
|
||||
use Lucent\Core\Schema\Data\FieldProp\FieldProp;
|
||||
use Lucent\Core\Schema\Data\Schema;
|
||||
use Lucent\Id\Id;
|
||||
use Lucent\Svelte\Svelte;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class FieldController extends Controller
|
||||
{
|
||||
public function __construct(private readonly Svelte $svelte) {}
|
||||
|
||||
public function create(Request $request)
|
||||
{
|
||||
$schemaId = $request->input("schema");
|
||||
$fieldType = $request->input("type");
|
||||
|
||||
$schemas = SchemaRepo::all();
|
||||
$schema = collect($schemas)->firstWhere("id", $schemaId);
|
||||
|
||||
if (empty($schema)) {
|
||||
return response()->json(["error" => "Schema not found"], 404);
|
||||
}
|
||||
if (empty($fieldType)) {
|
||||
return response()->json(["error" => "Field type not found"], 404);
|
||||
}
|
||||
|
||||
// $fieldProps = FieldProp::fromType($fieldType);
|
||||
|
||||
return $this->svelte->render(
|
||||
view: "fieldCreate",
|
||||
title: "Create Field",
|
||||
data: [
|
||||
"schemas" => $schemas,
|
||||
"schema" => $schema,
|
||||
// "fieldProps" => $fieldProps,
|
||||
"type" => $fieldType,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
public function postCreate(Request $request)
|
||||
{
|
||||
$schemaId = $request->input("schemaId");
|
||||
$name = $request->input("name");
|
||||
$alias = $request->input("alias");
|
||||
$fieldType = $request->input("fieldType");
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
"name" => "required|string|max:30|min:2",
|
||||
"alias" => "required|alpha_dash:ascii|max:30|min:2",
|
||||
"schemaId" => "required",
|
||||
"fieldType" => "required",
|
||||
]);
|
||||
if ($validator->fails()) {
|
||||
return response()->json(["errors" => $validator->errors()], 422);
|
||||
}
|
||||
|
||||
$schemas = SchemaRepo::all();
|
||||
$schema = collect($schemas)->firstWhere("id", $schemaId);
|
||||
|
||||
$fieldProps = FieldProp::fromType($fieldType);
|
||||
|
||||
$field = new Field(
|
||||
id: Id::new(),
|
||||
schemaId: $schemaId,
|
||||
name: $name,
|
||||
alias: $alias,
|
||||
type: $fieldType,
|
||||
props: $fieldProps,
|
||||
);
|
||||
|
||||
FieldRepo::insert($field);
|
||||
return response()->json(["field" => $field], 201);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ use Lucent\Http\Controller\AccountController;
|
||||
use Lucent\Http\Controller\AuthController;
|
||||
use Lucent\Http\Controller\BuildController;
|
||||
use Lucent\Http\Controller\EdgeController;
|
||||
use Lucent\Http\Controller\FieldController;
|
||||
use Lucent\Http\Controller\FileController;
|
||||
use Lucent\Http\Controller\HomeController;
|
||||
use Lucent\Http\Controller\MemberController;
|
||||
@@ -61,6 +62,8 @@ Route::group(
|
||||
]);
|
||||
Route::get("/schemas", [SchemaController::class, "home"]);
|
||||
Route::post("/schemas", [SchemaController::class, "postCreate"]);
|
||||
Route::get("/fields/create", [FieldController::class, "create"]);
|
||||
Route::post("/fields", [FieldController::class, "postCreate"]);
|
||||
});
|
||||
|
||||
Route::middleware(["lucent.auth"])->group(function () {
|
||||
|
||||
Reference in New Issue
Block a user