cleanup
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
export let name;
|
export let name;
|
||||||
export let side = "48";
|
export let side = 48;
|
||||||
const colors = [
|
const colors = [
|
||||||
"#00AA55",
|
"#00AA55",
|
||||||
"#009FD4",
|
"#009FD4",
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import {getContext, onMount} from "svelte";
|
import {getContext, onMount} from "svelte";
|
||||||
import SpinnerButton from "../common/SpinnerButton.svelte";
|
|
||||||
import ErrorAlert from "../common/ErrorAlert.svelte";
|
|
||||||
import MemberSettingsCard from "../members/MemberSettingsCard.svelte";
|
|
||||||
import SuccessAlert from "../common/SuccessAlert.svelte";
|
|
||||||
import Radio from "../forms/Radio.svelte";
|
|
||||||
|
|
||||||
const channel = getContext("channel");
|
const channel = getContext("channel");
|
||||||
export let title;
|
export let title;
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
<script>
|
|
||||||
import Icon from "./Icon.svelte";
|
|
||||||
|
|
||||||
export let label = "";
|
|
||||||
export let show = false;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn btn-link p-0 text-decoration-none d-flex align-items-center mb-2 "
|
|
||||||
on:click|preventDefault={(e) => (show = !show)}
|
|
||||||
>
|
|
||||||
<span class="me-1">{label}</span>
|
|
||||||
{#if !show}
|
|
||||||
<Icon icon="circle-chevron-down" />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if show}
|
|
||||||
<Icon icon="circle-chevron-up" />
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
{#if show}
|
|
||||||
<div class="mb-3" style="padding: 22px; background: rgb(249, 249, 249); border-radius: 32px;">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="rounded w-100"
|
class="rounded w-100"
|
||||||
src={imgurl(record, imageSide, imageSide, "crop")}
|
src={imgurl(record)}
|
||||||
alt={record._file.path}
|
alt={record._file.path}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,31 +1,11 @@
|
|||||||
import {getContext} from "svelte";
|
import {getContext} from "svelte";
|
||||||
|
|
||||||
export function imgurl(record, width = "", height = "", mode = "") {
|
export function imgurl(record) {
|
||||||
// let argumentString = "-o";
|
|
||||||
// if (mode) {
|
|
||||||
// argumentString += "-mode_fit";
|
|
||||||
// }
|
|
||||||
// if (width) {
|
|
||||||
// argumentString += "-w_" + width;
|
|
||||||
// }
|
|
||||||
// if (height) {
|
|
||||||
// argumentString += "-h_" + height;
|
|
||||||
// }
|
|
||||||
// let pathAr = record._file.path.split(".");
|
|
||||||
// let ext = pathAr.pop();
|
|
||||||
// let filename = record._file.path.replace("." + ext, "");
|
|
||||||
// let cache = "cache/"
|
|
||||||
// if (!mode && !width && !height) {
|
|
||||||
// argumentString = "";
|
|
||||||
// cache = "";
|
|
||||||
// }
|
|
||||||
|
|
||||||
const channel = getContext("channel")
|
const channel = getContext("channel")
|
||||||
return channel.filesUrl + `/thumbs/${record._file.path}`;
|
return channel.filesUrl + `/thumbs/${record._file.path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fileurl(record) {
|
export function fileurl(record) {
|
||||||
|
|
||||||
const channel = getContext("channel")
|
const channel = getContext("channel")
|
||||||
return channel.filesUrl + `/${record._file.path}`;
|
return channel.filesUrl + `/${record._file.path}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { uniqueId } from "lodash";
|
|
||||||
export let label;
|
|
||||||
export let value;
|
|
||||||
let id = uniqueId();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="form-check">
|
|
||||||
<input
|
|
||||||
value=""
|
|
||||||
class="form-check-input"
|
|
||||||
type="checkbox"
|
|
||||||
bind:checked={value}
|
|
||||||
id={id}
|
|
||||||
/>
|
|
||||||
<label class="form-check-label" for={id}>
|
|
||||||
{label}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { uniqueId } from "lodash";
|
|
||||||
export let label;
|
|
||||||
export let value;
|
|
||||||
let id = uniqueId();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if label}
|
|
||||||
<div class="d-flex justify-content-between">
|
|
||||||
<label for={id} class="form-label">{label}</label>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="input-group ">
|
|
||||||
<div style="width:64px;">
|
|
||||||
<input
|
|
||||||
type="color"
|
|
||||||
class="form-control form-control-color"
|
|
||||||
bind:value
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<input type="text" {id} class="form-control" bind:value />
|
|
||||||
</div>
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import flatpickr from "flatpickr";
|
|
||||||
import "flatpickr/dist/flatpickr.css";
|
|
||||||
import "flatpickr/dist/themes/light.css";
|
|
||||||
|
|
||||||
import { uniqueId } from "lodash";
|
|
||||||
export let label;
|
|
||||||
export let value;
|
|
||||||
let pickerInput;
|
|
||||||
let id = uniqueId();
|
|
||||||
|
|
||||||
let flatpickrOptions = {
|
|
||||||
enableTime: false,
|
|
||||||
allowInput: true,
|
|
||||||
dateFormat: "Y-m-d",
|
|
||||||
defaultDate: value,
|
|
||||||
};
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
flatpickr(pickerInput, flatpickrOptions);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if label}
|
|
||||||
<div class="d-flex justify-content-between">
|
|
||||||
<label for={id} class="form-label">{label}</label>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
{id}
|
|
||||||
class="form-control"
|
|
||||||
bind:value
|
|
||||||
bind:this={pickerInput}
|
|
||||||
autocomplete="off"
|
|
||||||
/>
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { onMount, onDestroy, tick } from "svelte";
|
|
||||||
|
|
||||||
import tinymce from "tinymce/tinymce";
|
|
||||||
import "tinymce/models/dom";
|
|
||||||
import "tinymce/icons/default";
|
|
||||||
import "tinymce/themes/silver";
|
|
||||||
import "tinymce/skins/ui/oxide/skin.css";
|
|
||||||
import contentUiSkinCss from "tinymce/skins/ui/oxide/content.css";
|
|
||||||
|
|
||||||
import "tinymce/plugins/link";
|
|
||||||
import "tinymce/plugins/code";
|
|
||||||
import "tinymce/plugins/image";
|
|
||||||
import "tinymce/plugins/table";
|
|
||||||
import "tinymce/plugins/codesample";
|
|
||||||
import "tinymce/plugins/media";
|
|
||||||
|
|
||||||
import "tinymce/plugins/lists";
|
|
||||||
import "tinymce/plugins/autoresize";
|
|
||||||
import "tinymce/plugins/wordcount";
|
|
||||||
import BrowseModal from "../records/elements/BrowseModal.svelte";
|
|
||||||
|
|
||||||
export let schemas;
|
|
||||||
export let schema;
|
|
||||||
export let field;
|
|
||||||
export let value = "";
|
|
||||||
export let additionalConfig = {};
|
|
||||||
let browseModal;
|
|
||||||
let lastVal = "";
|
|
||||||
let textareaEl;
|
|
||||||
let activeEditor;
|
|
||||||
let editorWrapper;
|
|
||||||
const plugins = [
|
|
||||||
"autoresize",
|
|
||||||
"code",
|
|
||||||
"image",
|
|
||||||
"table",
|
|
||||||
"codesample",
|
|
||||||
"link",
|
|
||||||
"lists",
|
|
||||||
"media",
|
|
||||||
"wordcount",
|
|
||||||
];
|
|
||||||
const toolbar =
|
|
||||||
"bold italic underline strikethrough removeformat | link image fileManager | subscript superscript bullist numlist media codesample table code wordcount blockquote indent outdent blocks";
|
|
||||||
|
|
||||||
onDestroy(() => {
|
|
||||||
if (activeEditor) {
|
|
||||||
activeEditor.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const config = {
|
|
||||||
target: textareaEl,
|
|
||||||
toolbar_mode: "sliding",
|
|
||||||
toolbar_sticky: true,
|
|
||||||
skin: false,
|
|
||||||
content_css: false,
|
|
||||||
content_style: contentUiSkinCss.toString(),
|
|
||||||
branding: false,
|
|
||||||
inline: false,
|
|
||||||
plugins: plugins,
|
|
||||||
contextmenu: false,
|
|
||||||
menubar: false,
|
|
||||||
statusbar: false,
|
|
||||||
entity_encoding: "raw",
|
|
||||||
convert_urls: false,
|
|
||||||
toolbar: toolbar,
|
|
||||||
image_caption: true,
|
|
||||||
relative_urls: false,
|
|
||||||
browser_spellcheck: true,
|
|
||||||
max_height: 600,
|
|
||||||
// media_poster: false,
|
|
||||||
// content_style:
|
|
||||||
// "body {font-family: 'Averta Std', sans serif; color: #152F77}",
|
|
||||||
setup: function (editor) {
|
|
||||||
activeEditor = editor;
|
|
||||||
|
|
||||||
editor.on("init", function (e) {
|
|
||||||
editor.setContent(value ?? "");
|
|
||||||
});
|
|
||||||
|
|
||||||
// editor.on("blur", function (e) {
|
|
||||||
// let content = setImageDimensions(editor.getContent());
|
|
||||||
// dispatch("editorBlur", content);
|
|
||||||
// editorWrapper.classList.remove("editorFocus");
|
|
||||||
// // return false;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// editor.on("focus", function (e) {
|
|
||||||
// editorWrapper.classList.add("editorFocus");
|
|
||||||
// // return false;
|
|
||||||
// });
|
|
||||||
|
|
||||||
editor.on("change input undo redo", function (e) {
|
|
||||||
lastVal = editor.getContent();
|
|
||||||
if (lastVal !== value) {
|
|
||||||
value = lastVal;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.ui.registry.addMenuButton("fileManager", {
|
|
||||||
icon: "upload",
|
|
||||||
fetch: (callback) => {
|
|
||||||
const items = field.collections.map((c) => {
|
|
||||||
return {
|
|
||||||
type: "menuitem",
|
|
||||||
text:
|
|
||||||
schemas.find((s) => s.name == c).label ??
|
|
||||||
"Schema missing",
|
|
||||||
onAction: () => {
|
|
||||||
openBrowseModal(c);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
callback(items);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tinymce.init({ ...config, ...additionalConfig });
|
|
||||||
});
|
|
||||||
|
|
||||||
function openBrowseModal(aschema) {
|
|
||||||
browseModal.open(aschema);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function insert(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const recordsToInsert = e.detail.records;
|
|
||||||
let fileSchema = schemas.find(
|
|
||||||
(s) => s.name === recordsToInsert[0]._sys.schema
|
|
||||||
);
|
|
||||||
let contentTonInsert = recordsToInsert
|
|
||||||
.map((r) => {
|
|
||||||
if (r._file.mime.startsWith("image")) {
|
|
||||||
let fileUrl =
|
|
||||||
fileSchema.objectStorageProxy + "/" + r._file.path;
|
|
||||||
return `<img src="${fileUrl}" alt="${r._file.path}" width="${r._file.width}" height="${r._file.height}" />`;
|
|
||||||
} else {
|
|
||||||
let fileUrl =
|
|
||||||
fileSchema.objectStorageUrl + "/" + r._file.path;
|
|
||||||
return `<a href="${fileUrl}" title="${r._file.path}">${r._file.path}</a>`;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.join("<br />");
|
|
||||||
|
|
||||||
activeEditor.insertContent(contentTonInsert);
|
|
||||||
await tick();
|
|
||||||
browseModal.close();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div bind:this={editorWrapper} class="tox-wrapper">
|
|
||||||
<div class="form-control" bind:this={textareaEl}>
|
|
||||||
{@html value}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if field && schema}
|
|
||||||
<BrowseModal bind:this={browseModal} on:insert={insert} />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
:global(.tox:not(.tox-tinymce-inline) .tox-editor-header) {
|
|
||||||
background-color: #fff;
|
|
||||||
border-bottom: 1px solid #ced4da;
|
|
||||||
box-shadow: none;
|
|
||||||
padding: 4px 0;
|
|
||||||
transition: box-shadow 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.tox-tinymce) {
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Channel;
|
|
||||||
|
|
||||||
|
|
||||||
use Lucent\Validator\Validator;
|
|
||||||
|
|
||||||
class PreviewTarget
|
|
||||||
{
|
|
||||||
function __construct(
|
|
||||||
public readonly string $label,
|
|
||||||
public readonly string $url,
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Validator::single("label", $label, "required|min:2|max:50");
|
|
||||||
Validator::single("url", $url, "required|url");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fromArray(array $data): PreviewTarget
|
|
||||||
{
|
|
||||||
|
|
||||||
return new PreviewTarget(
|
|
||||||
label: $data["label"],
|
|
||||||
url: $data["url"],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Edge;
|
|
||||||
|
|
||||||
|
|
||||||
final class QueryEdge
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
public string $fromSchema,
|
|
||||||
public string $from,
|
|
||||||
public string $schema,
|
|
||||||
public string $field,
|
|
||||||
public string $to,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Primitive;
|
|
||||||
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @extends \Illuminate\Support\Collection<int|string, string>
|
|
||||||
*/
|
|
||||||
final class StringCollection extends Collection
|
|
||||||
{
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
string ...$array
|
|
||||||
) {
|
|
||||||
parent::__construct($array);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]
|
|
||||||
**/
|
|
||||||
public function toArray(): array
|
|
||||||
{
|
|
||||||
return collect($this)->values()->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fromArray(array $data): StringCollection
|
|
||||||
{
|
|
||||||
return new StringCollection(...$data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fromDB(string $data): StringCollection
|
|
||||||
{
|
|
||||||
return new StringCollection(...\json_decode($data,true));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Support;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An in-memory memoizer that keeps the cached values around for the lifetime of this instance.
|
|
||||||
*/
|
|
||||||
class Memoize
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The saved results
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private array $cache = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* $cacheTime is ignored - this will keep the results around for the lifetime of this instance.
|
|
||||||
*
|
|
||||||
* @see Memoize::memoizeCallable
|
|
||||||
*
|
|
||||||
* @param string $key
|
|
||||||
* @param callable $compute
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function memoizeCallable(string $key, callable $compute) :mixed
|
|
||||||
{
|
|
||||||
if (array_key_exists($key, $this->cache)) {
|
|
||||||
return $this->cache[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $compute();
|
|
||||||
$this->cache[$key] = $result;
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user