edges wip
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
<RecordForm
|
||||
{channel}
|
||||
fields={data.fields}
|
||||
edgeRecordPreviews={data.edgeRecordPreviewsDraft}
|
||||
{record}
|
||||
{selectedLocales}
|
||||
validationErrors={data.validationErrors}
|
||||
@@ -53,6 +54,7 @@
|
||||
<RecordForm
|
||||
{channel}
|
||||
fields={data.fields}
|
||||
edgeRecordPreviews={data.edgeRecordPreviewsLive}
|
||||
{record}
|
||||
{selectedLocales}
|
||||
validationErrors={data.validationErrors}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
channel,
|
||||
validationErrors,
|
||||
fieldData,
|
||||
edgeRecordPreviews,
|
||||
selectedLocales,
|
||||
} = $props();
|
||||
|
||||
const findFieldValidationError = (field, locale) => {
|
||||
return validationErrors.find(
|
||||
(f) => f.fieldId === field.id && f.locale === locale,
|
||||
@@ -20,6 +20,12 @@
|
||||
(f) => f.fieldId === field.id && f.locale === locale,
|
||||
);
|
||||
};
|
||||
$inspect(edgeRecordPreviews);
|
||||
const findFieldEdges = (field, locale) => {
|
||||
return edgeRecordPreviews.filter(
|
||||
(e) => e.edge.fieldId === field.id && e.edge.locale === locale,
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
{#each fields as field}
|
||||
@@ -62,5 +68,6 @@
|
||||
schemaField={field}
|
||||
{locale}
|
||||
dataField={findDataField(field, locale)}
|
||||
edgeRecordPreviews={findFieldEdges(field, locale)}
|
||||
></RelationField>
|
||||
{/snippet}
|
||||
|
||||
@@ -2,8 +2,15 @@
|
||||
import { get, post } from "../../../modules/remote";
|
||||
import { getApp } from "../../../app";
|
||||
import { getLocaleName } from "../locale.svelte.js";
|
||||
let { channel, record, schemaField, dataField, locale, validationError } =
|
||||
$props();
|
||||
let {
|
||||
channel,
|
||||
record,
|
||||
schemaField,
|
||||
dataField,
|
||||
locale,
|
||||
validationError,
|
||||
edgeRecordPreviews,
|
||||
} = $props();
|
||||
let originalValue = dataField?.value ?? schemaField.props.default;
|
||||
let newValue = $state(originalValue);
|
||||
let valuesChanged = $derived(newValue !== originalValue);
|
||||
@@ -14,9 +21,12 @@
|
||||
|
||||
let suggestionsLoaded = $state(false);
|
||||
let suggestions = $state([]);
|
||||
let selectedRecordIds = $state([]);
|
||||
let dialog = $state();
|
||||
|
||||
function handleAddRecord(e) {
|
||||
function handleModalOpen(e) {
|
||||
// Add logic to handle adding a record
|
||||
dialog.showModal();
|
||||
if (suggestionsLoaded) {
|
||||
return;
|
||||
}
|
||||
@@ -30,26 +40,24 @@
|
||||
);
|
||||
}
|
||||
|
||||
function save() {
|
||||
if (!valuesChanged) {
|
||||
return;
|
||||
}
|
||||
function handleModalClose(e) {
|
||||
dialog.close();
|
||||
}
|
||||
|
||||
function handleInsertSelected() {
|
||||
suggestionsLoaded = false;
|
||||
post(
|
||||
app.url("records/fields"),
|
||||
app.url("edges/many"),
|
||||
{
|
||||
recordId: record.id,
|
||||
id: schemaField.id,
|
||||
toIds: selectedRecordIds,
|
||||
from: record.id,
|
||||
fieldId: schemaField.id,
|
||||
locale: locale,
|
||||
value: newValue,
|
||||
},
|
||||
(data, err) => {
|
||||
if (err.isNotEmpty()) {
|
||||
errorMessage = err.first();
|
||||
} else {
|
||||
validationError = data.validationError;
|
||||
originalValue = newValue;
|
||||
}
|
||||
suggestionsLoaded = true;
|
||||
dialog.close();
|
||||
edgeRecordPreviews = [...edgeRecordPreviews, ...data];
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -61,26 +69,68 @@
|
||||
{getLocaleName(channel, locale)} >
|
||||
{/if}
|
||||
{schemaField.name} <br />
|
||||
<details class="dropdown">
|
||||
<summary onclick={handleAddRecord}>Add Record</summary>
|
||||
</label>
|
||||
{#if hasError}
|
||||
<small id={schemaField.id + "-help"}>{validationError.message}</small>
|
||||
{:else if schemaField.help != ""}
|
||||
<small id={schemaField.id + "-help"}>{schemaField.help}</small>
|
||||
{/if}
|
||||
|
||||
<button onclick={handleModalOpen}>Choose record</button>
|
||||
|
||||
<dialog bind:this={dialog}>
|
||||
<article>
|
||||
<header>
|
||||
<button onclick={handleModalClose} aria-label="Close" rel="prev"
|
||||
></button>
|
||||
<p>
|
||||
<strong>Records</strong>
|
||||
</p>
|
||||
</header>
|
||||
{#if suggestionsLoaded}
|
||||
<ul>
|
||||
{#each suggestions as suggestion}
|
||||
<li><a href="#">{suggestion.title}</a></li>
|
||||
{/each}
|
||||
<li><a href="#">More</a></li>
|
||||
</ul>
|
||||
<form>
|
||||
<button onclick={handleInsertSelected}>
|
||||
Insert selected
|
||||
</button>
|
||||
<table>
|
||||
<tbody>
|
||||
{#each suggestions as suggestion}
|
||||
<tr>
|
||||
<td>
|
||||
<input
|
||||
type="checkbox"
|
||||
value={suggestion.id}
|
||||
bind:group={selectedRecordIds}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#">{suggestion.title}</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#">
|
||||
{suggestion.schemaName}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
{:else}
|
||||
<progress />
|
||||
{/if}
|
||||
</details>
|
||||
|
||||
{#if hasError}
|
||||
<small id={schemaField.id + "-help"}
|
||||
>{validationError.message}</small
|
||||
>
|
||||
{:else if schemaField.help != ""}
|
||||
<small id={schemaField.id + "-help"}>{schemaField.help}</small>
|
||||
</article>
|
||||
</dialog>
|
||||
<div>
|
||||
{#if edgeRecordPreviews.length == 0}
|
||||
No relations exist
|
||||
{:else}
|
||||
{#each edgeRecordPreviews as edgeRecordPreview}
|
||||
<div>
|
||||
<a href="#">{edgeRecordPreview.recordPreview.title}</a>
|
||||
{edgeRecordPreview.recordPreview.schemaName}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php namespace Lucent\Core\Data;
|
||||
use Lucent\Core\Data\RecordMode;
|
||||
class Edge
|
||||
{
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public string $locale,
|
||||
public RecordMode $mode,
|
||||
public string $from,
|
||||
public string $to,
|
||||
public string $fieldId,
|
||||
public int $rank,
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php namespace Lucent\Core\Data;
|
||||
|
||||
class EdgeRecordPreview
|
||||
{
|
||||
public function __construct(
|
||||
public Edge $edge,
|
||||
public RecordPreview $recordPreview,
|
||||
) {}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ class RecordPreview
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public string $schemaId,
|
||||
public string $schemaName,
|
||||
public string $title,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php namespace Lucent\Core\Edge;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Lucent\Core\Data\Edge;
|
||||
use Lucent\Core\Data\RecordMode;
|
||||
use stdClass;
|
||||
|
||||
class EdgeModule
|
||||
{
|
||||
public static function toDb(Edge $edge): array
|
||||
{
|
||||
return [
|
||||
"id" => $edge->id,
|
||||
"locale" => $edge->locale,
|
||||
"mode" => $edge->mode->value,
|
||||
"from" => $edge->from,
|
||||
"to" => $edge->to,
|
||||
"field_id" => $edge->fieldId,
|
||||
"rank" => $edge->rank,
|
||||
];
|
||||
}
|
||||
|
||||
public static function fromDb(stdClass $data): Edge
|
||||
{
|
||||
return new Edge(
|
||||
id: data_get($data, "id"),
|
||||
locale: data_get($data, "locale"),
|
||||
mode: RecordMode::from(data_get($data, "mode")),
|
||||
from: data_get($data, "from"),
|
||||
to: data_get($data, "to"),
|
||||
fieldId: data_get($data, "field_id"),
|
||||
rank: data_get($data, "rank"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ use Carbon\Carbon;
|
||||
use Lucent\Core\Data\Record;
|
||||
use Lucent\Core\Data\RecordPreview;
|
||||
use Lucent\Core\Data\RecordStatus;
|
||||
use Lucent\Core\Data\EdgeRecordPreview;
|
||||
use Lucent\Core\Edge\EdgeModule;
|
||||
use stdClass;
|
||||
|
||||
class RecordModule
|
||||
@@ -68,12 +70,45 @@ class RecordModule
|
||||
);
|
||||
}
|
||||
|
||||
public static function recordPreviewFromDb(stdClass $data): RecordPreview
|
||||
{
|
||||
/**
|
||||
* @param Schema[] $schemas
|
||||
* @param stdClass $data
|
||||
* @return RecordPreview
|
||||
*/
|
||||
public static function recordPreviewFromDb(
|
||||
array $schemas,
|
||||
stdClass $data,
|
||||
): RecordPreview {
|
||||
return new RecordPreview(
|
||||
id: data_get($data, "id"),
|
||||
schemaId: data_get($data, "schema_id"),
|
||||
schemaName: collect($schemas)
|
||||
->where("id", data_get($data, "schema_id"))
|
||||
->first()->name,
|
||||
|
||||
title: data_get($data, "title"),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema[] $schemas
|
||||
* @param stdClass $data
|
||||
* @return EdgeRecordPreview
|
||||
*/
|
||||
public static function edgeRecordPreviewFromDb(
|
||||
array $schemas,
|
||||
stdClass $data,
|
||||
): EdgeRecordPreview {
|
||||
return new EdgeRecordPreview(
|
||||
edge: EdgeModule::fromDb($data),
|
||||
recordPreview: new RecordPreview(
|
||||
id: data_get($data, "record_id"),
|
||||
schemaId: data_get($data, "record_schema_id"),
|
||||
schemaName: collect($schemas)
|
||||
->where("id", data_get($data, "record_schema_id"))
|
||||
->first()->name,
|
||||
title: data_get($data, "record_title"),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php namespace Lucent\Core\Repository;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Core\Data\Edge;
|
||||
use Lucent\Core\Edge\EdgeModule;
|
||||
|
||||
class EdgeRepo
|
||||
{
|
||||
const TABLE_NAME = "edges";
|
||||
|
||||
/**
|
||||
* Insert multiple edges into the database.
|
||||
*
|
||||
* @param Edge[] $edges An array of Edge objects to be inserted.
|
||||
*/
|
||||
public static function insertMany(array $edges): void
|
||||
{
|
||||
DB::table(self::TABLE_NAME)->insert(
|
||||
array_map(EdgeModule::toDb(...), $edges),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Lucent\Core\Data\Record;
|
||||
use Lucent\Core\Data\RecordPreview;
|
||||
use Lucent\Core\Data\EdgeRecordPreview;
|
||||
use Lucent\Core\Record\RecordModule;
|
||||
|
||||
class RecordRepo
|
||||
@@ -30,18 +31,20 @@ class RecordRepo
|
||||
->first();
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* @param Schema[] $schemas
|
||||
* @return RecordPreview[]
|
||||
*/
|
||||
public static function findBySchemas(array $schemas): array
|
||||
{
|
||||
$schemaIds = array_map(fn($schema) => $schema->id, $schemas);
|
||||
return DB::table(self::TABLE_NAME)
|
||||
->select(
|
||||
"records.id",
|
||||
"records.schema_id",
|
||||
"records_data.value as title",
|
||||
)
|
||||
->whereIn("schema_id", $schemas)
|
||||
->whereIn("schema_id", $schemaIds)
|
||||
->join("records_data", function ($join) {
|
||||
$join
|
||||
->on("records.id", "=", "records_data.record_id")
|
||||
@@ -54,8 +57,45 @@ class RecordRepo
|
||||
->orderBy("created_at", "desc")
|
||||
->limit(5)
|
||||
->get()
|
||||
->map(fn($row) => RecordModule::recordPreviewFromDb($schemas, $row))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
->map(RecordModule::recordPreviewFromDb(...))
|
||||
/**
|
||||
* @param Schema[] $schemas
|
||||
* @return EdgeRecordPreview[]
|
||||
*/
|
||||
public static function findEdgeRecordPreviewsByRecordId(
|
||||
array $schemas,
|
||||
string $recordId,
|
||||
): array {
|
||||
return DB::table("edges")
|
||||
->select(
|
||||
"edges.*",
|
||||
"records.id as record_id",
|
||||
"records.schema_id as record_schema_id",
|
||||
"records_data.value as record_title",
|
||||
)
|
||||
->where("edges.from", $recordId)
|
||||
->join("records", "edges.from", "=", "records.id")
|
||||
->join("records_data", function ($join) {
|
||||
$join
|
||||
->on("records.id", "=", "records_data.record_id")
|
||||
->on(
|
||||
"records.title_field_id",
|
||||
"=",
|
||||
"records_data.field_id",
|
||||
);
|
||||
})
|
||||
->orderBy("edges.rank", "asc")
|
||||
->get()
|
||||
|
||||
->map(
|
||||
fn($row) => RecordModule::edgeRecordPreviewFromDb(
|
||||
$schemas,
|
||||
$row,
|
||||
),
|
||||
)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,19 @@ class SchemaRepo
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Schema[]
|
||||
*/
|
||||
public static function findByIds(array $schemaIds): array
|
||||
{
|
||||
return DB::table(self::TABLE_NAME)
|
||||
->whereIn("id", $schemaIds)
|
||||
->orderBy("name")
|
||||
->get()
|
||||
->map(SchemaModule::fromDb(...))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function findOne(string $id): ?Schema
|
||||
{
|
||||
return DB::table(self::TABLE_NAME)
|
||||
|
||||
@@ -4,10 +4,36 @@ namespace Lucent\Http\Controller;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Lucent\Edge\EdgeService;
|
||||
use Lucent\Query\Query;
|
||||
use Lucent\Core\Repository\EdgeRepo;
|
||||
use Lucent\Core\Data\Edge;
|
||||
use Lucent\Core\Data\RecordMode;
|
||||
use Lucent\Id\Id;
|
||||
use function Lucent\Response\fail;
|
||||
use function Lucent\Response\ok;
|
||||
|
||||
class EdgeController extends Controller
|
||||
{
|
||||
public function postCreate(Request $request) {}
|
||||
public function postCreateMany(Request $request)
|
||||
{
|
||||
$from = $request->input("from");
|
||||
$toIds = $request->input("toIds");
|
||||
$fieldId = $request->input("fieldId");
|
||||
$locale = $request->input("locale");
|
||||
|
||||
$edges = array_map(
|
||||
fn($to) => new Edge(
|
||||
id: Id::new(),
|
||||
from: $from,
|
||||
to: $to,
|
||||
fieldId: $fieldId,
|
||||
locale: $locale,
|
||||
rank: 0,
|
||||
mode: RecordMode::DRAFT,
|
||||
),
|
||||
$toIds,
|
||||
);
|
||||
|
||||
EdgeRepo::insertMany($edges);
|
||||
return ok($edges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,19 @@ class RecordController
|
||||
);
|
||||
|
||||
$recordStatus = RecordModule::getStatus($record);
|
||||
$edgeRecordPreviews = RecordRepo::findEdgeRecordPreviewsByRecordId(
|
||||
$schemas,
|
||||
$record->id,
|
||||
);
|
||||
$edgeRecordPreviewsDraft = collect($edgeRecordPreviews)
|
||||
->where("edge.mode", RecordMode::DRAFT)
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
$edgeRecordPreviewsLive = collect($edgeRecordPreviews)
|
||||
->where("edge.mode", RecordMode::LIVE)
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
return Svelte::view(
|
||||
view: "recordEdit",
|
||||
@@ -191,7 +204,8 @@ class RecordController
|
||||
"schemas" => $schemas,
|
||||
"schema" => $schema,
|
||||
"fields" => $fields,
|
||||
// "graph" => toArray($graph),
|
||||
"edgeRecordPreviewsDraft" => toArray($edgeRecordPreviewsDraft),
|
||||
"edgeRecordPreviewsLive" => toArray($edgeRecordPreviewsLive),
|
||||
"record" => toArray($record),
|
||||
"draftData" => $draftData,
|
||||
"liveData" => $liveData,
|
||||
@@ -203,7 +217,9 @@ class RecordController
|
||||
|
||||
public function suggest(Request $request)
|
||||
{
|
||||
$schemas = $request->input("schemas");
|
||||
$schemaIds = $request->input("schemas");
|
||||
$schemas = SchemaRepo::findByIds($schemaIds);
|
||||
|
||||
$records = RecordRepo::findBySchemas($schemas);
|
||||
return ok(toArray($records));
|
||||
}
|
||||
|
||||
@@ -98,6 +98,12 @@ Route::group(
|
||||
RecordController::class,
|
||||
"untrash",
|
||||
]);
|
||||
|
||||
// EDGES
|
||||
Route::post("edges/many", [
|
||||
EdgeController::class,
|
||||
"postCreateMany",
|
||||
]);
|
||||
});
|
||||
|
||||
//OLD
|
||||
|
||||
Reference in New Issue
Block a user