wip content index
This commit is contained in:
@@ -45,5 +45,15 @@ return [
|
||||
\Lucent\Schema\Ui\Slug::class,
|
||||
\Lucent\Schema\Ui\Text::class,
|
||||
\Lucent\Schema\Ui\Textarea::class
|
||||
],
|
||||
"renderers" => [
|
||||
"row" => [
|
||||
"file" => \Lucent\Schema\Renderer\Row\File::class,
|
||||
"slug" => \Lucent\Schema\Renderer\Row\Text::class,
|
||||
"text" => \Lucent\Schema\Renderer\Row\Text::class,
|
||||
"checkbox" => \Lucent\Schema\Renderer\Row\Text::class,
|
||||
"number" => \Lucent\Schema\Renderer\Row\Text::class,
|
||||
"rich" => \Lucent\Schema\Renderer\Row\Text::class,
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -6,10 +6,14 @@ import Mustache from "mustache";
|
||||
import 'htmx.org';
|
||||
import {dropdown} from "./components/dropdown.js";
|
||||
import {colorPicker} from "./recordEditor/colorPicker.js";
|
||||
import {sortReferences} from "./recordEditor/sortReferences.js";
|
||||
import {recordDialog} from "./recordEditor/recordDialog.js";
|
||||
|
||||
addEventListener("load", (event) => {
|
||||
dropdown()
|
||||
colorPicker()
|
||||
sortReferences()
|
||||
recordDialog()
|
||||
});
|
||||
|
||||
Mustache.escape = function (value) {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import axios from "axios";
|
||||
|
||||
export function recordDialog() {
|
||||
|
||||
document.querySelectorAll("[data-open-modal]").forEach(el => {
|
||||
const schema = el.dataset.openModal
|
||||
el.addEventListener("click", e => {
|
||||
load(schema)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function load(schema) {
|
||||
axios
|
||||
.get("/lucent/content/" + schema)
|
||||
.then((response) => {
|
||||
|
||||
const dialogWrapperEl = document.createElement("div");
|
||||
dialogWrapperEl.innerHTML = response.data;
|
||||
document.body.appendChild(dialogWrapperEl);
|
||||
const dialogEl = dialogWrapperEl.querySelector("dialog");
|
||||
dialogEl.showModal();
|
||||
dialogWrapperEl.querySelector(".close").addEventListener("click", e => dialogEl.close());
|
||||
|
||||
dialogEl.addEventListener("close", (event) => {
|
||||
dialogWrapperEl.remove();
|
||||
});
|
||||
})
|
||||
.catch((error) => console.log(error));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import Sortable from "sortablejs";
|
||||
export function sortReferences() {
|
||||
document.querySelectorAll(".color-picker").forEach(el => {
|
||||
|
||||
let options = {
|
||||
animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
|
||||
easing: "cubic-bezier(1, 0, 0, 1)",
|
||||
direction: 'vertical',
|
||||
onUpdate: function (/**Event*/ evt) {
|
||||
// dispatch("update", {
|
||||
// source: evt.oldIndex,
|
||||
// target: evt.newIndex,
|
||||
// });
|
||||
}
|
||||
};
|
||||
|
||||
Sortable.create(el, options);
|
||||
})
|
||||
}
|
||||
@@ -11,7 +11,8 @@
|
||||
/* max-width: 128px; */
|
||||
max-height: 24px;
|
||||
text-overflow: ellipsis;
|
||||
/* white-space: nowrap; */
|
||||
overflow: hidden;
|
||||
/* white-space: nowrap; */
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -55,7 +55,11 @@
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
&.field-ui-number,&.field-ui-slug,&.field-ui-text,&.field-ui-rich,&.field-ui-url{
|
||||
max-height: 24px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
//img{
|
||||
// width: 48px;
|
||||
//}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
return strtoupper($segs[0][0]).strtoupper($segs[0][1]);
|
||||
};
|
||||
|
||||
$name = $user["name"];
|
||||
$name = (string)data_get($user,"name");
|
||||
$charIndex = ord($name[1]) + strlen($name);
|
||||
$colorIndex = $charIndex % 19;
|
||||
$bgColor = $colors[$colorIndex];
|
||||
@@ -39,5 +39,5 @@
|
||||
title="{{$name}}"
|
||||
style="background-color:{{$bgColor}};height: {{$side}}px;width: {{$side}}px; font-size:{{$side / 2}}px"
|
||||
>
|
||||
<div class="avatar__letters">{{$initials($user["name"])}}</div>
|
||||
<div class="avatar__letters">{{$initials($name)}}</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="checkbox-wrapper">
|
||||
<input id="c1-13" type="checkbox" value="{{$value}}" {{$indeterminate ?? false ? "indeterminate" : ""}} {{$checked ?? false ? "checked" : ""}} />
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
<dialog id="dialog-{{$schema->name}}">
|
||||
|
||||
|
||||
@if($schema)
|
||||
<div class="dialog-header">
|
||||
<button
|
||||
type="button"
|
||||
class="button"
|
||||
disabled
|
||||
>
|
||||
Insert
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="button"
|
||||
disabled
|
||||
>
|
||||
Replace
|
||||
</button>
|
||||
|
||||
<div class="hide">
|
||||
<span class="number-of-records-selected"></span> records selected
|
||||
</div>
|
||||
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="button close"
|
||||
aria-label="Close"
|
||||
>
|
||||
<x-lucent::icon icon="close">
|
||||
|
||||
</x-lucent::icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="dialog-body">
|
||||
@include("lucent::records.index")
|
||||
</div>
|
||||
|
||||
@endif
|
||||
</dialog>
|
||||
@@ -18,5 +18,6 @@
|
||||
@include("lucent::records-editor.fields", ["field" => $field])
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
@php
|
||||
$references = $graph->edges
|
||||
->filter(fn($edge) => $edge->field === $field->name && $edge->source === $record->id)
|
||||
->map(fn($edge) => $graph->records->firstWhere("id", $edge->target));
|
||||
$references = $graph->edges
|
||||
->filter(fn($edge) => $edge->field === $field->name && $edge->source === $record->id)
|
||||
->map(fn($edge) => $graph->records->firstWhere("id", $edge->target));
|
||||
|
||||
$collectionSchemas = $schemas->whereIn("name",$field->collections);
|
||||
@endphp
|
||||
|
||||
@if ($references->isNotEmpty())
|
||||
{{--<Sortable sortableClass="mt-3" on:update={reorder}>--}}
|
||||
@foreach($references as $reference)
|
||||
<!--This div helps the sorting thing-->
|
||||
<div>
|
||||
@include("lucent::records-editor.fields.file.preview")
|
||||
</div>
|
||||
@endforeach
|
||||
<!--</Sortable>-->
|
||||
@if(count($field->collections) === 1)
|
||||
<button class="button" data-open-modal="{{$field->collections[0]}}">Browse</button>
|
||||
@else
|
||||
<x-lucent::dropdown>
|
||||
Browse
|
||||
<x-slot:items>
|
||||
@foreach($collectionSchemas as $collectionSchema)
|
||||
<a class="dropdown-item" data-open-modal="{{$collectionSchema->name}}" href="/">{{$collectionSchema->label}}</a>
|
||||
@endforeach
|
||||
</x-slot:items>
|
||||
</x-lucent::dropdown>
|
||||
@endif
|
||||
|
||||
@if ($references->isNotEmpty())
|
||||
<div class="sortable-container mt-3">
|
||||
@foreach($references as $reference)
|
||||
<!--This div helps the sorting thing-->
|
||||
<div>
|
||||
@include("lucent::records-editor.fields.file.preview", ["record" => $reference])
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
@php
|
||||
$schema = $channel->schemas->firstWhere("name",$reference->schema);
|
||||
$reference = $record;
|
||||
$schema = $channel->schemas->firstWhere("name",$record->schema);
|
||||
@endphp
|
||||
|
||||
<div class="preview-file">
|
||||
<div style="display: flex;align-items: center;gap: 10px;">
|
||||
<div class="image">
|
||||
@include("lucent::records-editor.fields.file.thumb", ["size" => "small", "record" => $reference])
|
||||
@include("lucent::records-editor.fields.file.thumb", ["size" => "small"])
|
||||
</div>
|
||||
<div class="title">
|
||||
<div>
|
||||
<a class="record-title" href="{{lucent_url("records")}}/{{$record->id}}">
|
||||
{{$viewModel->getRecordName($reference)}}
|
||||
{{$viewModel->getRecordName($record)}}
|
||||
</a>
|
||||
<small class="d-block">
|
||||
from {{$schema->label}}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
<div class="">
|
||||
<div class="{{$inModal ? 'mt-0' : 'mt-5'}}">
|
||||
<h3 class="header-normal mb-5 ">
|
||||
{{$schema->label}}
|
||||
</h3>
|
||||
{{-- {#if selected.length > 0 && !inModal && isWritable}--}}
|
||||
{{-- <ActionsOnSelected {schema} {selected} {filter}/>--}}
|
||||
{{-- {:else}--}}
|
||||
{{-- <Tools--}}
|
||||
{{-- bind:schema--}}
|
||||
{{-- bind:records--}}
|
||||
{{-- {systemFields}--}}
|
||||
{{-- {sortParam}--}}
|
||||
{{-- {sortField}--}}
|
||||
{{-- {operators}--}}
|
||||
{{-- {filter}--}}
|
||||
{{-- {graph}--}}
|
||||
{{-- {inModal}--}}
|
||||
{{-- {modalUrl}--}}
|
||||
{{-- {isWritable}--}}
|
||||
{{-- on:refresh={refresh}--}}
|
||||
{{-- />--}}
|
||||
{{-- {/if}--}}
|
||||
@include("lucent::records.table")
|
||||
</div>
|
||||
|
||||
{{-- <Pagination--}}
|
||||
{{-- {limit}--}}
|
||||
{{-- {skip}--}}
|
||||
{{-- {total}--}}
|
||||
{{-- on:refresh={refresh}--}}
|
||||
{{-- {inModal}--}}
|
||||
{{-- {modalUrl}--}}
|
||||
{{-- />--}}
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
@extends("lucent::layouts.channel")
|
||||
|
||||
@section("content")
|
||||
@include("lucent::records.index")
|
||||
|
||||
@endsection
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
@foreach($schema->visible as $visibleColumn)
|
||||
@php
|
||||
$schemaField = $schema->fields->firstWhere("name", $visibleColumn);
|
||||
@endphp
|
||||
<td class="field-ui-{{$schemaField->info->name ?? $visibleColumn}} {{$visibleColumn === $sortField->name ? "is-sort" : ""}}">
|
||||
@if(in_array($visibleColumn ,["_sys.createdBy","_sys.updatedBy"]))
|
||||
<x-lucent::avatar side="24" :user="$users->firstWhere('id',$record->_sys->createdBy)"></x-lucent::avatar>
|
||||
@elseif($visibleColumn === "_sys.status")
|
||||
@include("lucent::records-editor.status",[ "status" => $record->status])
|
||||
@else
|
||||
{!! $viewModel->renderRow($record,$schemaField)!!}
|
||||
@endif
|
||||
</td>
|
||||
@endforeach
|
||||
@@ -0,0 +1,91 @@
|
||||
@php
|
||||
|
||||
@endphp
|
||||
|
||||
<div class="table mt-5 ">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@if($isWritable)
|
||||
<th>
|
||||
<x-lucent::checkbox value=""></x-lucent::checkbox>
|
||||
</th>
|
||||
@endif
|
||||
@foreach($schema->visible as $visibleColumn)
|
||||
@php
|
||||
$schemaField = $schema->fields->firstWhere("name", $visibleColumn);
|
||||
if(empty($schemaField)){
|
||||
$schemaField = collect($systemFields)->firstWhere("name", str_replace("_sys.", "",$visibleColumn) );
|
||||
}
|
||||
@endphp
|
||||
<th
|
||||
class="field-ui-{{$schemaField->info->name ?? $schemaField->ui}} {{$schemaField->name === $sortField->name ? "is-sort" : ""}}"
|
||||
scope="col"
|
||||
title={{$schemaField->help ?? ""}}
|
||||
>{{$schemaField->label}}</th
|
||||
>
|
||||
@endforeach
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($records as $record)
|
||||
<tr>
|
||||
<td class="title-td">
|
||||
<div
|
||||
class="title-td-contents"
|
||||
>
|
||||
@if($isWritable)
|
||||
<x-lucent::checkbox :value="$record->id"></x-lucent::checkbox>
|
||||
|
||||
@endif
|
||||
@if($record->_file?->path)
|
||||
<div class="file-table-row">
|
||||
@include("lucent::records-editor.fields.file.thumb", ["size" => "small"])
|
||||
<div>
|
||||
@if($record->status === "draft")
|
||||
<span style="text-transform: uppercase;font-size:10px">{{$record->status}}</span>
|
||||
@endif
|
||||
<a
|
||||
href="{{lucent_url("records")}}/{{$record->id}}"
|
||||
target={{$inModal ? "_blank" : "_self"}}
|
||||
>
|
||||
{{ $viewModel->getRecordName($record)}}
|
||||
</a>
|
||||
<span>{{ (int)($record->_file->size / 1024) }}kB</span>
|
||||
|
||||
@if($record->_file->width > 0)
|
||||
<span>{{$record->_file->width . "x" . $record->_file->height}}</span>
|
||||
@endif
|
||||
<a
|
||||
href="{{lucent_file($record)}}"
|
||||
target="_blank"
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@else
|
||||
<a
|
||||
href="{{lucent_url("records")}}/{{$record->id}}"
|
||||
target={{$inModal ? "_blank" : "_self"}}
|
||||
>
|
||||
@if($record->status === "draft")
|
||||
<span style="text-transform: uppercase;font-size:10px">{{$record->status}}</span>
|
||||
@endif
|
||||
{{$viewModel->getRecordName($record)}}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
@include("lucent::records.row")
|
||||
<td>
|
||||
<x-lucent::avatar side="24"
|
||||
:user="$users->firstWhere('id',$record->_sys->createdBy)"></x-lucent::avatar>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -79,14 +79,15 @@ class RecordController extends Controller
|
||||
->runWithCount();
|
||||
|
||||
|
||||
$records = $graph->getRootRecords()->toArray();
|
||||
|
||||
|
||||
$data = [
|
||||
"schemas" => $this->channelService->channel->schemas,
|
||||
"schema" => $schema,
|
||||
"users" => $users,
|
||||
"records" => $records,
|
||||
"records" => $graph->tree(),
|
||||
"graph" => toArray($graph),
|
||||
"visibleFields" => array_values(System::list()),
|
||||
"systemFields" => array_values(System::list()),
|
||||
"operators" => $this->operatorRegistry->all(),
|
||||
"sortParam" => $sort,
|
||||
@@ -104,9 +105,10 @@ class RecordController extends Controller
|
||||
if (str_starts_with(config("lucent.url"), "https")) {
|
||||
$data["modalUrl"] = str_replace("http://", "https://", $request->fullUrl());
|
||||
}
|
||||
return $data;
|
||||
return view("lucent::records-editor.dialog", $data)->render();
|
||||
}
|
||||
$data["inModal"] = false;
|
||||
return view("lucent::records.list", $data);
|
||||
return $this->svelte->render(
|
||||
layout: "channel",
|
||||
view: "contentIndex",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Schema\Renderer\Row;
|
||||
|
||||
use Lucent\Record\QueryRecord;
|
||||
use Lucent\Schema\FieldInterface;
|
||||
|
||||
class File implements IRowRenderer
|
||||
{
|
||||
|
||||
public function __invoke(QueryRecord $record, FieldInterface $field): string
|
||||
{
|
||||
$reference = data_get($record,"_children.".$field->name);
|
||||
if(!isset($reference[0])){
|
||||
return "";
|
||||
}
|
||||
return view("lucent::records-editor.fields.file.thumb",["size" => "tiny", "record" => $reference[0]])->render();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Schema\Renderer\Row;
|
||||
|
||||
use Lucent\Record\QueryRecord;
|
||||
use Lucent\Schema\FieldInterface;
|
||||
|
||||
interface IRowRenderer
|
||||
{
|
||||
public function __invoke(QueryRecord $record, FieldInterface $field):string;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Lucent\Schema\Renderer\Row;
|
||||
|
||||
use Lucent\Record\QueryRecord;
|
||||
use Lucent\Schema\FieldInterface;
|
||||
|
||||
class Text implements IRowRenderer
|
||||
{
|
||||
|
||||
public function __invoke(QueryRecord $record, FieldInterface $field): string
|
||||
{
|
||||
return data_get($record,"data.".$field->name,"");
|
||||
}
|
||||
}
|
||||
@@ -37,4 +37,11 @@ class ViewModel
|
||||
$m = new Mustache_Engine(array('entity_flags' => ENT_QUOTES));
|
||||
return $m->render($schema->cardTitle, $record->data);
|
||||
}
|
||||
|
||||
public function renderRow(QueryRecord $record, FieldInterface $field): string
|
||||
{
|
||||
$renderers = config("lucent.renderers.row");
|
||||
return (new $renderers[$field->info->name])($record, $field);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user