build editor

This commit is contained in:
2023-10-23 18:05:06 +03:00
parent e2e3842cd0
commit 9346969d2b
19 changed files with 534 additions and 206 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{
"main.js": {
"file": "assets/main.1ef17975.js",
"file": "assets/main.7f90168e.js",
"src": "main.js",
"isEntry": true,
"css": [
@@ -0,0 +1,61 @@
<script>
// https://codesandbox.io/s/codemirror-remark-editor-4m4z9?file=/src/CodeEditor.js:374-387
import {onMount, onDestroy} from "svelte";
import {basicSetup, EditorView} from "codemirror";
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
import {EditorState, Compartment} from "@codemirror/state";
import {keymap} from "@codemirror/view";
import {indentWithTab} from "@codemirror/commands";
import {markdown} from "@codemirror/lang-markdown";
import {lintKeymap} from "@codemirror/lint";
let parentElement;
let codeMirrorView;
export let value;
export let editable = true;
onMount(() => {
let language = new Compartment();
let tabSize = new Compartment();
let state = EditorState.create({
doc: value,
extensions: [
basicSetup,
keymap.of([
indentWithTab,
...lintKeymap,
...completionKeymap
]),
language.of(markdown()),
markdown(),
autocompletion(),
tabSize.of(EditorState.tabSize.of(4)),
basicSetup,
EditorView.editable.of(editable),
EditorView.updateListener.of(function (e) {
if (e.docChanged) {
value = e.state.doc.toString();
}
}),
EditorView.lineWrapping
],
});
codeMirrorView = new EditorView({
state,
parent: parentElement,
});
});
onDestroy(() => {
if (codeMirrorView) {
codeMirrorView.destroy();
}
});
</script>
<div class="is-editable-{editable}" bind:this={parentElement}/>
+2
View File
@@ -15,6 +15,7 @@
import Datetime from "./elements/Datetime.svelte";
import RichEditor from "./elements/RichEditor.svelte";
import Json from "./elements/JSON.svelte";
import Markdown from "./elements/Markdown.svelte";
import FieldHeader from "./elements/FieldHeader.svelte";
import ReferenceTable from "./elements/ReferenceTable.svelte";
import ReferenceTags from "./elements/ReferenceTags.svelte";
@@ -32,6 +33,7 @@
datetime: Datetime,
uuid: UUID,
json: Json,
markdown: Markdown,
};
export let field;
+2 -3
View File
@@ -49,9 +49,9 @@
let schema = channel.schemas.find((s) => s.name === record.schema);
let edgeField = findEdgeField(schema,edge.field);
// let schemaField = edge.targetSchema + edgeField;
let schemaField = edge.targetSchema + edgeField;
// let schemaField = edge.targetSchema + edgeField;
let schemaField = edgeField.name + edge.targetSchema;
if (!carry[schemaField]) {
carry[schemaField] = {
@@ -67,7 +67,6 @@
carry[schemaField].nodes.push(arecord);
carry[schemaField].nodes = uniqBy(carry[schemaField].nodes,"id");
}
return carry;
}, {});
</script>
@@ -11,7 +11,6 @@
export let value = [];
export let graph;
let blockSchema = channel.schemas.find((s) => s.name === field.schema);
</script>
@@ -2,11 +2,10 @@
import Icon from "../../common/Icon.svelte";
import {insertBlock} from "./block";
export let blockId;
export let blockId = "";
export let blockData;
export let blockSchema;
$: showOptions = false;
let validUis = ["heading", "textarea", "rich", "reference"];
function createBlock(e, ui) {
e.preventDefault();
@@ -2,6 +2,7 @@
import Heading from "./elements/Heading.svelte";
import Textarea from "./elements/Textarea.svelte";
import Rich from "./elements/Rich.svelte";
import Markdown from "./elements/Markdown.svelte";
import Reference from "./elements/Reference.svelte";
import Icon from "../../common/Icon.svelte";
import {insertBlock} from "./block";
@@ -125,6 +126,10 @@
<Rich
bind:block={block}
/>
{:else if block.meta.info.name === "markdown"}
<Markdown
bind:block={block}
/>
{:else if block.meta.info.name === "file"}
<File
{record}
@@ -0,0 +1,15 @@
<script>
import Codemirror from "../../../libs/CodemirrorMarkdown.svelte";
export let block;
// export let id;
</script>
<div class="mb-3">
<Codemirror bind:value={block.value} />
</div>
@@ -0,0 +1,24 @@
<script>
import Codemirror from "../../libs/CodemirrorMarkdown.svelte";
import { getErrorMessage } from "./errorMessage";
export let value;
export let field;
export let isCreateMode;
// export let id;
export let validationErrors;
$: errorMessage = getErrorMessage(validationErrors, field.name);
</script>
<div class="mb-3">
<Codemirror bind:value editable={!field.readonly || isCreateMode} />
{#if errorMessage}
<div class="invalid-feedback d-block">
{errorMessage}
</div>
{/if}
</div>
+101 -16
View File
@@ -4,6 +4,9 @@
"requires": true,
"packages": {
"": {
"dependencies": {
"@codemirror/lang-markdown": "^6.2.2"
},
"devDependencies": {
"@codemirror/commands": "^6.1.2",
"@codemirror/lang-json": "^6.0.1",
@@ -44,7 +47,6 @@
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.9.1.tgz",
"integrity": "sha512-yma56tqD7khIZK4gy4X5lX3/k5ArMiCGat7HEWRF/8L2kqOjVdp2qKZqpcJjwTIjSj6fqKAHqi7IjtH3QFE+Bw==",
"dev": true,
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
@@ -70,6 +72,48 @@
"@lezer/common": "^1.0.0"
}
},
"node_modules/@codemirror/lang-css": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@lezer/common": "^1.0.2",
"@lezer/css": "^1.0.0"
}
},
"node_modules/@codemirror/lang-html": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.6.tgz",
"integrity": "sha512-E4C8CVupBksXvgLSme/zv31x91g06eZHSph7NczVxZW+/K+3XgJGWNT//2WLzaKSBoxpAjaOi5ZnPU1SHhjh3A==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/lang-css": "^6.0.0",
"@codemirror/lang-javascript": "^6.0.0",
"@codemirror/language": "^6.4.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/css": "^1.1.0",
"@lezer/html": "^1.3.0"
}
},
"node_modules/@codemirror/lang-javascript": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.1.tgz",
"integrity": "sha512-jlFOXTejVyiQCW3EQwvKH0m99bUYIw40oPmFjSX2VS78yzfe0HELZ+NEo9Yfo1MkGRpGlj3Gnu4rdxV1EnAs5A==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.6.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/javascript": "^1.0.0"
}
},
"node_modules/@codemirror/lang-json": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
@@ -80,11 +124,24 @@
"@lezer/json": "^1.0.0"
}
},
"node_modules/@codemirror/lang-markdown": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.2.tgz",
"integrity": "sha512-wmwM9Y5n/e4ndU51KcYDaQnb9goYdhXjU71dDW9goOc1VUTIPph6WKAPdJ6BzC0ZFy+UTsDwTXGWSP370RH69Q==",
"dependencies": {
"@codemirror/autocomplete": "^6.7.1",
"@codemirror/lang-html": "^6.0.0",
"@codemirror/language": "^6.3.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0",
"@lezer/markdown": "^1.0.0"
}
},
"node_modules/@codemirror/language": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.1.tgz",
"integrity": "sha512-lWRP3Y9IUdOms6DXuBpoWwjkR7yRmnS0hKYCbSfPz9v6Em1A1UCRujAkDiCrdYfs1Z0Eu4dGtwovNPStIfkgNA==",
"dev": true,
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
@@ -98,7 +155,6 @@
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz",
"integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==",
"dev": true,
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
@@ -119,14 +175,12 @@
"node_modules/@codemirror/state": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz",
"integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==",
"dev": true
"integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw=="
},
"node_modules/@codemirror/view": {
"version": "6.20.2",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.20.2.tgz",
"integrity": "sha512-tZ9F0UZU2P3eTRtgljg3DaCOTn2FIjQU/ktTCjSz9/6he3GHDNxSCDAPidMtF+09r23o0h9H/5U7xibtUuEgdg==",
"dev": true,
"dependencies": {
"@codemirror/state": "^6.1.4",
"style-mod": "^4.1.0",
@@ -181,18 +235,44 @@
"node_modules/@lezer/common": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.0.tgz",
"integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw==",
"dev": true
"integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw=="
},
"node_modules/@lezer/css": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.3.tgz",
"integrity": "sha512-SjSM4pkQnQdJDVc80LYzEaMiNy9txsFbI7HsMgeVF28NdLaAdHNtQ+kB/QqDUzRBV/75NTXjJ/R5IdC8QQGxMg==",
"dependencies": {
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/highlight": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz",
"integrity": "sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==",
"dev": true,
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/html": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.6.tgz",
"integrity": "sha512-Kk9HJARZTc0bAnMQUqbtuhFVsB4AnteR2BFUWfZV7L/x1H0aAKz6YabrfJ2gk/BEgjh9L3hg5O4y2IDZRBdzuQ==",
"dependencies": {
"@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/javascript": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.8.tgz",
"integrity": "sha512-QRmw/5xrcyRLyWr3JT3KCzn2XZr5NYNqQMGsqnYy+FghbQn9DZPuj6JDkE6uSXvfMLpdapu8KBIaeoJFaR4QVw==",
"dependencies": {
"@lezer/highlight": "^1.1.3",
"@lezer/lr": "^1.3.0"
}
},
"node_modules/@lezer/json": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.1.tgz",
@@ -207,11 +287,19 @@
"version": "1.3.12",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.12.tgz",
"integrity": "sha512-5nwY1JzCueUdRtlMBnlf1SUi69iGCq2ABq7WQFQMkn/kxPvoACAEnTp4P17CtXxYr7WCwtYPLL2AEvxKPuF1OQ==",
"dev": true,
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/markdown": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.1.0.tgz",
"integrity": "sha512-JYOI6Lkqbl83semCANkO3CKbKc0pONwinyagBufWBm+k4yhIcqfCF8B8fpEpvJLmIy7CAfwiq7dQ/PzUZA340g==",
"dependencies": {
"@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
@@ -364,8 +452,7 @@
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"dev": true
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
},
"node_modules/date-fns": {
"version": "2.30.0",
@@ -1144,8 +1231,7 @@
"node_modules/style-mod": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz",
"integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==",
"dev": true
"integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA=="
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
@@ -1346,8 +1432,7 @@
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"dev": true
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
}
}
}
+3 -1
View File
@@ -28,5 +28,7 @@
"vis-network": "^9.1.2",
"vite": "^3.2.3"
},
"dependencies": {}
"dependencies": {
"@codemirror/lang-markdown": "^6.2.2"
}
}
+4 -4
View File
@@ -64,8 +64,8 @@ final class ChannelService
public function schemasReadableByRoles(array $roles): array
{
$schemasAllRead = $this->channel->schemas->filter(fn(Schema $schema) => empty($schema->read))->values()->pluck("name");
$schemasCanRead = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->read, $roles)) > 0)->values()->pluck("name");
$schemasCanWrite = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->write, $roles)) > 0)->values()->pluck("name");
$schemasCanRead = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->read ?? [], $roles)) > 0)->values()->pluck("name");
$schemasCanWrite = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->write ?? [], $roles)) > 0)->values()->pluck("name");
return $schemasAllRead->merge($schemasCanRead)->merge($schemasCanWrite)->unique()->values()->toArray();
}
@@ -76,8 +76,8 @@ final class ChannelService
*/
public function schemasWritableByRoles(array $roles): array
{
$schemasAllRead = $this->channel->schemas->filter(fn(Schema $schema) => empty($schema->write))->values()->pluck("name");
$schemasCanWrite = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->write, $roles)) > 0)->values()->pluck("name");
$schemasAllRead = $this->channel->schemas->filter(fn(Schema $schema) => empty($schema->write ?? []))->values()->pluck("name");
$schemasCanWrite = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->write ?? [], $roles)) > 0)->values()->pluck("name");
return $schemasAllRead->merge($schemasCanWrite)->unique()->values()->toArray();
}
+13 -1
View File
@@ -22,9 +22,21 @@ class Record implements JsonSerializable
}
private function indexValues(array $arrObject){
return trim(Str::lower(collect($arrObject)
->map(function($value){
if(!is_string($value)){
return $this->indexValues($value ?? []);
}
return $value;
})
->values()->join(" ")." ". $this->_file?->originalName ?? ""));
}
public function toDB(): array
{
$searchIndex = trim(Str::lower(collect($this->data)->values()->join(" ")." ". $this->_file?->originalName ?? ""));
$searchIndex = $this->indexValues($this->data->toArray());
return [
"id" => $this->id,
"status" => $this->status->value,
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Lucent\Schema\BlockUi;
use Lucent\Schema\FieldInfo;
use Lucent\Schema\FieldInterface;
use Lucent\Schema\FieldType;
use Lucent\Schema\Nullable;
use Lucent\Schema\Validator\RequiredInterface;
class Markdown implements FieldInterface
{
public FieldInfo $info;
public function __construct(
public string $name,
public string $label,
public ?int $min = null,
public ?int $max = null,
public string $default = "",
)
{
$this->info = new FieldInfo("markdown", "Markdown Editor", FieldType::STRING);
}
public function format(array $input, array $output): array
{
$output[$this->name] = $input[$this->name] ?? "";
return $output;
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Lucent\Schema\BlockUi;
use Lucent\Schema\FieldInfo;
use Lucent\Schema\FieldInterface;
use Lucent\Schema\FieldType;
use Lucent\Schema\Nullable;
use Lucent\Schema\Validator\RequiredInterface;
class Rich implements FieldInterface
{
public FieldInfo $info;
public function __construct(
public string $name,
public string $label,
public ?int $min = null,
public ?int $max = null,
public string $default = "",
)
{
$this->info = new FieldInfo("rich", "Rich Editor", FieldType::STRING);
}
public function format(array $input, array $output): array
{
$output[$this->name] = $input[$this->name] ?? "";
return $output;
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace Lucent\Schema\Ui;
use Lucent\Schema\FieldInfo;
use Lucent\Schema\FieldInterface;
use Lucent\Schema\FieldType;
use Lucent\Schema\Nullable;
use Lucent\Schema\Validator\RequiredInterface;
class Markdown implements FieldInterface, RequiredInterface
{
public FieldInfo $info;
public function __construct(
public string $name,
public string $label,
public bool $required = false,
public bool $nullable = false,
public string $default = "",
public string $help = "",
public ?int $min = null,
public ?int $max = null,
public bool $readonly = false,
public string $group = "",
)
{
$this->info = new FieldInfo("markdown", "Markdown editor", FieldType::STRING);
}
public function format(array $input, array $output): array
{
$value = $input[$this->name] ?? null;
$output[$this->name] = (new Nullable($this->nullable, $value, ""))->value();
return $output;
}
public function failRequired(mixed $value): bool
{
return empty(trim($value));
}
}
+6 -6
View File
@@ -7,13 +7,13 @@
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title') - Lucent Data Platform</title>
<!-- if development -->
@php
echo '<script type="module" crossorigin src="http://127.0.0.1:5173/@vite/client"></script>';
@endphp
<script type="module" crossorigin src="http://127.0.0.1:5173/main.js"></script>
{{-- @php--}}
{{-- echo '<script type="module" crossorigin src="http://127.0.0.1:5173/@vite/client"></script>';--}}
{{-- @endphp--}}
{{-- <script type="module" crossorigin src="http://127.0.0.1:5173/main.js"></script>--}}
<!-- if production -->
{{-- <link rel="stylesheet" href="/vendor/lucent/dist/{{ $manifest['main.css']["file"] }}" />--}}
{{-- <script type="module" src="/vendor/lucent/dist/{{ $manifest['main.js']["file"] }}"></script>--}}
<link rel="stylesheet" href="/vendor/lucent/dist/{{ $manifest['main.css']["file"] }}" />
<script type="module" src="/vendor/lucent/dist/{{ $manifest['main.js']["file"] }}"></script>
<link rel="icon" type="image/x-icon" href="/favicon.ico">