cleanup
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
LUCENT_AUTH=lucent // or lunar
|
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import RecordRow from "./RecordRow.svelte";
|
import RecordRow from "./RecordRow.svelte";
|
||||||
import { previewTitle } from "../records/Preview";
|
|
||||||
import { usernameById } from "../account/users";
|
import { usernameById } from "../account/users";
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
import Avatar from "../account/Avatar.svelte";
|
import Avatar from "../account/Avatar.svelte";
|
||||||
import { selectRecord, toggleAll } from "./functions/recordSelect.js";
|
import { selectRecord, toggleAll } from "./functions/recordSelect.js";
|
||||||
import Checkbox from "../common/Checkbox.svelte";
|
import Checkbox from "../common/Checkbox.svelte";
|
||||||
import Preview from "../files/Preview.svelte";
|
|
||||||
import { fileurl } from "../files/imageserver.js";
|
|
||||||
|
|
||||||
const channel = getContext("channel");
|
const channel = getContext("channel");
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import {createEventDispatcher, getContext} from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import {previewTitle} from "../../records/Preview";
|
|
||||||
import Icon from "../../common/Icon.svelte";
|
import Icon from "../../common/Icon.svelte";
|
||||||
|
|
||||||
const channel = getContext("channel");
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
export let schema;
|
export let schema;
|
||||||
export let operators;
|
export let operators;
|
||||||
@@ -19,13 +17,10 @@
|
|||||||
isReference: key.startsWith("children"),
|
isReference: key.startsWith("children"),
|
||||||
};
|
};
|
||||||
|
|
||||||
filter = [
|
filter = [extractOperator(key), extractLabel(schema, key)].reduce(
|
||||||
extractOperator(key),
|
(mem, fn) => fn(mem),
|
||||||
extractLabel(schema, key),
|
filter,
|
||||||
].reduce((mem, fn) => fn(mem), filter);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function extractOperator(key) {
|
function extractOperator(key) {
|
||||||
return (filter) => {
|
return (filter) => {
|
||||||
@@ -50,18 +45,16 @@
|
|||||||
const filterField = schema.fields.find((f) => f.name === fieldName);
|
const filterField = schema.fields.find((f) => f.name === fieldName);
|
||||||
filter.label = filterField?.label ?? fieldName;
|
filter.label = filterField?.label ?? fieldName;
|
||||||
return filter;
|
return filter;
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterRecord = extractFilterRecord(graph, value);
|
const filterRecord = extractFilterRecord(graph, value);
|
||||||
|
|
||||||
function extractFilterRecord(graph, value) {
|
function extractFilterRecord(graph, value) {
|
||||||
|
|
||||||
if (!filter.isReference) {
|
if (!filter.isReference) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return graph.records.find(r => r.id === value);
|
return graph.records.find((r) => r.id === value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFilter(k) {
|
function removeFilter(k) {
|
||||||
@@ -78,19 +71,21 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span class="applied-filter">
|
<span class="applied-filter">
|
||||||
|
{#if filter.isReference && filterRecord}
|
||||||
|
{filter.label} is {filterRecord.data.name}
|
||||||
|
{:else}
|
||||||
|
{filter.label}
|
||||||
|
{operators.find((o) => o.name === filter.operator)?.symbol ?? ""}
|
||||||
|
{operators.find((o) => o.name === filter.operator)?.hasValue
|
||||||
|
? value
|
||||||
|
: ""}
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if filter.isReference && filterRecord}
|
<button
|
||||||
{filter.label} is {previewTitle(channel.schemas, filterRecord)}
|
on:click|preventDefault={() => removeFilter(key)}
|
||||||
{:else}
|
type="button"
|
||||||
{filter.label} {operators.find((o) => o.name === filter.operator)?.symbol ?? ""} {operators.find((o) => o.name === filter.operator)?.hasValue ? value : ""}
|
class="button-text"
|
||||||
{/if}
|
aria-label="Close"
|
||||||
|
><Icon width={12} height={12} icon="close"></Icon></button
|
||||||
<button
|
>
|
||||||
on:click|preventDefault={() => removeFilter(key)}
|
|
||||||
type="button"
|
|
||||||
class="button-text"
|
|
||||||
aria-label="Close"
|
|
||||||
><Icon width={12} height={12} icon="close"></Icon></button>
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import {createEventDispatcher, getContext} from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import {debounce} from "lodash";
|
import { debounce } from "lodash";
|
||||||
import {previewTitle} from "../../records/Preview";
|
|
||||||
|
|
||||||
|
|
||||||
const channel = getContext("channel");
|
const channel = getContext("channel");
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
@@ -10,9 +8,8 @@
|
|||||||
export let value = "";
|
export let value = "";
|
||||||
export let field;
|
export let field;
|
||||||
|
|
||||||
let search = ""
|
let search = "";
|
||||||
$: searchOptions = []
|
$: searchOptions = [];
|
||||||
|
|
||||||
|
|
||||||
const updateResults = debounce((e) => {
|
const updateResults = debounce((e) => {
|
||||||
axios
|
axios
|
||||||
@@ -35,46 +32,36 @@
|
|||||||
|
|
||||||
function apply(e, newOption) {
|
function apply(e, newOption) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
value = newOption.id
|
value = newOption.id;
|
||||||
dispatch("addFilter");
|
dispatch("addFilter");
|
||||||
value = ""
|
value = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="reference-tags">
|
<div class="reference-tags">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
on:keyup={updateResults}
|
on:keyup={updateResults}
|
||||||
bind:value={search}
|
bind:value={search}
|
||||||
placeholder={"Search for "+field.label}
|
placeholder={"Search for " + field.label}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="reference-tags-results">
|
<div class="reference-tags-results">
|
||||||
|
|
||||||
{#if searchOptions}
|
{#if searchOptions}
|
||||||
{#each searchOptions as option (option.id)}
|
{#each searchOptions as option (option.id)}
|
||||||
<div
|
<div
|
||||||
class="reference-tags-option"
|
class="reference-tags-option"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
on:click={(e) => apply(e, option)}
|
on:click={(e) => apply(e, option)}
|
||||||
on:keypress={(e) => apply(e, option)}
|
on:keypress={(e) => apply(e, option)}
|
||||||
>
|
>
|
||||||
{previewTitle(channel.schemas, option)}
|
{option.data.name}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{:else}
|
{:else}
|
||||||
<div
|
<div class="start-typing">Start typing...</div>
|
||||||
class="start-typing">
|
|
||||||
Start typing...
|
|
||||||
</div>
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { formatDistanceToNow, parseJSON } from "date-fns";
|
import { formatDistanceToNow, parseJSON } from "date-fns";
|
||||||
import Avatar from "../account/Avatar.svelte";
|
import Avatar from "../account/Avatar.svelte";
|
||||||
import { previewTitle } from "../records/Preview";
|
|
||||||
import Preview from "../files/Preview.svelte";
|
import Preview from "../files/Preview.svelte";
|
||||||
import { usernameById } from "../account/users";
|
import { usernameById } from "../account/users";
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
@@ -25,7 +24,7 @@
|
|||||||
<Preview {record} size="tiny" showFilename={true} />
|
<Preview {record} size="tiny" showFilename={true} />
|
||||||
{:else}
|
{:else}
|
||||||
<a href="{channel.lucentUrl}/records/{record.id}">
|
<a href="{channel.lucentUrl}/records/{record.id}">
|
||||||
{previewTitle(channel.schemas, record, graph)}
|
{record.data.name}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script>
|
<script>
|
||||||
import NavbarMenu from "./NavbarMenu.svelte";
|
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
export let schema;
|
export let schema;
|
||||||
@@ -9,13 +8,14 @@
|
|||||||
|
|
||||||
<div class="sidebar-top">
|
<div class="sidebar-top">
|
||||||
<a class="logo" href={channel.lucentUrl}>{channel.name}</a>
|
<a class="logo" href={channel.lucentUrl}>{channel.name}</a>
|
||||||
<a class="nav-item" href="{channel.lucentUrl}/profile"> </a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<NavbarMenu
|
{#each readableSchemas as aschema}
|
||||||
title="Content"
|
<a
|
||||||
schemas={readableSchemas.filter((sc) => sc.isEntry)}
|
class="sidebar-item"
|
||||||
{schema}
|
class:active={aschema.name === schema?.name}
|
||||||
expanded={true}
|
aria-current="page"
|
||||||
/>
|
href="{channel.lucentUrl}/content/{aschema.name}">{aschema.label}</a
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
<script>
|
|
||||||
import {getContext} from "svelte";
|
|
||||||
import Icon from "../common/Icon.svelte";
|
|
||||||
|
|
||||||
const channel = getContext("channel");
|
|
||||||
export let schemas;
|
|
||||||
export let title;
|
|
||||||
export let schema;
|
|
||||||
export let expanded = false;
|
|
||||||
|
|
||||||
if(schemas.find(s => s.name === schema?.name)){
|
|
||||||
expanded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleExpand(){
|
|
||||||
expanded = !expanded;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<button class="sidebar-header" tabindex="0" on:click={toggleExpand}>
|
|
||||||
{title}
|
|
||||||
{#if expanded}
|
|
||||||
<Icon icon="circle-chevron-up"></Icon>
|
|
||||||
{:else}
|
|
||||||
<Icon icon="circle-chevron-down"></Icon>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
{#if expanded}
|
|
||||||
{#each schemas as aschema}
|
|
||||||
<a class="sidebar-item" class:active={aschema.name === schema?.name}
|
|
||||||
aria-current="page"
|
|
||||||
href="{channel.lucentUrl}/content/{aschema.name}">{aschema.label}</a>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import Mustache from "mustache";
|
|
||||||
import { stripHtml } from "../../helpers";
|
|
||||||
|
|
||||||
export function previewTitle(schemas, record, graph) {
|
|
||||||
let schema = schemas.find((aSchema) => aSchema.name === record?.schema);
|
|
||||||
if (!schema?.cardTitle) {
|
|
||||||
return noTemplate(schema, record);
|
|
||||||
}
|
|
||||||
|
|
||||||
let recordData = record.data;
|
|
||||||
let render = Mustache.render(schema.cardTitle, recordData);
|
|
||||||
if (!render || render === "") {
|
|
||||||
return noTemplate(schema, record);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stripHtml(render.slice(0, 300));
|
|
||||||
}
|
|
||||||
|
|
||||||
function noTemplate(schema, record) {
|
|
||||||
if (schema?.type === "files") {
|
|
||||||
return file.path;
|
|
||||||
}
|
|
||||||
|
|
||||||
let title = stripHtml(
|
|
||||||
record?.data[schema.fields.filter((f) => f.info.name === "text")[0]?.name],
|
|
||||||
).slice(0, 300);
|
|
||||||
|
|
||||||
if (title.trim() === "") {
|
|
||||||
return "~Untitled~";
|
|
||||||
}
|
|
||||||
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import {previewTitle} from "./Preview";
|
import { getContext } from "svelte";
|
||||||
import {getContext} from "svelte";
|
|
||||||
|
|
||||||
const channel = getContext("channel");
|
const channel = getContext("channel");
|
||||||
export let record;
|
export let record;
|
||||||
export let graph;
|
$: title = record.data.name;
|
||||||
$: schema = channel.schemas.find((aschema) => aschema.name === record.schema);
|
|
||||||
|
|
||||||
$: title = previewTitle(channel.schemas, record, graph);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if record?.data}
|
{#if record?.data}
|
||||||
<a
|
<a href="{channel.lucentUrl}/records/{record.id}" {title} class="reference">
|
||||||
href="{channel.lucentUrl}/records/{record.id}"
|
|
||||||
{title}
|
|
||||||
class="reference"
|
|
||||||
>
|
|
||||||
{title}
|
{title}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import {getContext} from "svelte";
|
import { getContext } from "svelte";
|
||||||
import {debounce} from "lodash";
|
import { debounce } from "lodash";
|
||||||
import {previewTitle} from "../Preview";
|
import { getErrorMessage } from "./errorMessage";
|
||||||
import {getErrorMessage} from "./errorMessage";
|
import { insertEdges } from "./reference.js";
|
||||||
import {insertEdges} from "./reference.js";
|
|
||||||
import Icon from "../../common/Icon.svelte";
|
import Icon from "../../common/Icon.svelte";
|
||||||
|
|
||||||
const channel = getContext("channel");
|
const channel = getContext("channel");
|
||||||
@@ -15,20 +14,24 @@
|
|||||||
export let validationErrors;
|
export let validationErrors;
|
||||||
$: errorMessage = getErrorMessage(validationErrors, field.name);
|
$: errorMessage = getErrorMessage(validationErrors, field.name);
|
||||||
|
|
||||||
$: references = graph.edges
|
$: references =
|
||||||
.filter((edge) => edge.field === field.name)
|
graph.edges
|
||||||
.map((edge) => {
|
.filter((edge) => edge.field === field.name)
|
||||||
return graph.records.find((increc) => increc.id == edge.target && record.id == edge.source);
|
.map((edge) => {
|
||||||
}).filter((rec) => (rec?.id ? true : false)) ?? [];
|
return graph.records.find(
|
||||||
|
(increc) =>
|
||||||
let search = ""
|
increc.id == edge.target && record.id == edge.source,
|
||||||
$: searchOptions = []
|
);
|
||||||
|
})
|
||||||
|
.filter((rec) => (rec?.id ? true : false)) ?? [];
|
||||||
|
|
||||||
|
let search = "";
|
||||||
|
$: searchOptions = [];
|
||||||
|
|
||||||
function removeReference(e, recordId) {
|
function removeReference(e, recordId) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
graph.edges = graph.edges.filter(
|
graph.edges = graph.edges.filter(
|
||||||
(edge) => !(edge.target === recordId && edge.field === field.name)
|
(edge) => !(edge.target === recordId && edge.field === field.name),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,14 +44,14 @@
|
|||||||
schema: field.collections[0],
|
schema: field.collections[0],
|
||||||
status: "published",
|
status: "published",
|
||||||
data: {
|
data: {
|
||||||
[field.searchField]: newValue
|
[field.searchField]: newValue,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
searchOptions = [];
|
searchOptions = [];
|
||||||
insert(e, response.data.records[0]);
|
insert(e, response.data.records[0]);
|
||||||
console.log(response)
|
console.log(response);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
searchOptions = [];
|
searchOptions = [];
|
||||||
@@ -58,10 +61,16 @@
|
|||||||
|
|
||||||
function insert(e, insertRecord) {
|
function insert(e, insertRecord) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
graph = insertEdges(graph, record, [insertRecord], field.name, e.detail.action);
|
graph = insertEdges(
|
||||||
search = ""
|
graph,
|
||||||
searchEl.focus()
|
record,
|
||||||
searchEl.blur()
|
[insertRecord],
|
||||||
|
field.name,
|
||||||
|
e.detail.action,
|
||||||
|
);
|
||||||
|
search = "";
|
||||||
|
searchEl.focus();
|
||||||
|
searchEl.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateResults = debounce((e) => {
|
const updateResults = debounce((e) => {
|
||||||
@@ -82,9 +91,8 @@
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="reference-tags">
|
<div class="reference-tags">
|
||||||
{#if errorMessage}
|
{#if errorMessage}
|
||||||
<div class="invalid-feedback d-block mb-3">
|
<div class="invalid-feedback d-block mb-3">
|
||||||
@@ -93,44 +101,39 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
bind:this={searchEl}
|
bind:this={searchEl}
|
||||||
{id}
|
{id}
|
||||||
on:keyup={updateResults}
|
on:keyup={updateResults}
|
||||||
class:is-invalid={errorMessage}
|
class:is-invalid={errorMessage}
|
||||||
bind:value={search}
|
bind:value={search}
|
||||||
placeholder={"Search for "+field.label}
|
placeholder={"Search for " + field.label}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="reference-tags-results">
|
<div class="reference-tags-results">
|
||||||
|
|
||||||
{#if searchOptions}
|
{#if searchOptions}
|
||||||
{#each searchOptions as option (option.id)}
|
{#each searchOptions as option (option.id)}
|
||||||
<div
|
<div
|
||||||
class="reference-tags-option"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
on:click={(e) => insert(e, option)}
|
|
||||||
on:keypress={(e) => insert(e, option)}
|
|
||||||
>
|
|
||||||
{previewTitle(channel.schemas, option ,graph)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{:else}
|
|
||||||
<div
|
|
||||||
class="start-typing">
|
|
||||||
Start typing...
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
{#if search }
|
|
||||||
<div
|
|
||||||
class="reference-tags-option"
|
class="reference-tags-option"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
on:click={(e) => saveNew(e,search)}
|
on:click={(e) => insert(e, option)}
|
||||||
on:keypress={(e) => saveNew(e,search)}
|
on:keypress={(e) => insert(e, option)}
|
||||||
|
>
|
||||||
|
{option.data.name}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="start-typing">Start typing...</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{#if search}
|
||||||
|
<div
|
||||||
|
class="reference-tags-option"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
on:click={(e) => saveNew(e, search)}
|
||||||
|
on:keypress={(e) => saveNew(e, search)}
|
||||||
>
|
>
|
||||||
Add "{search}"
|
Add "{search}"
|
||||||
</div>
|
</div>
|
||||||
@@ -142,26 +145,23 @@
|
|||||||
<div style="display: flex;align-items: center;gap: 4px">
|
<div style="display: flex;align-items: center;gap: 4px">
|
||||||
{#each references as record (record.id)}
|
{#each references as record (record.id)}
|
||||||
<span class="reference-tags-selected-value">
|
<span class="reference-tags-selected-value">
|
||||||
<a
|
<a
|
||||||
class="record-title"
|
class="record-title"
|
||||||
href="{channel.lucentUrl}/records/{record.id}"
|
href="{channel.lucentUrl}/records/{record.id}"
|
||||||
>
|
>
|
||||||
{previewTitle(channel.schemas, record)}
|
{record.data.name}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click|preventDefault={(e) => removeReference(e, record.id)}
|
on:click|preventDefault={(e) =>
|
||||||
type="button"
|
removeReference(e, record.id)}
|
||||||
class="button-text"
|
type="button"
|
||||||
aria-label="Close"
|
class="button-text"
|
||||||
|
aria-label="Close"
|
||||||
>
|
>
|
||||||
<Icon width={12} height={12} icon="close"></Icon>
|
<Icon width={12} height={12} icon="close"></Icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
<script>
|
<script>
|
||||||
import {getContext} from "svelte";
|
import { getContext } from "svelte";
|
||||||
import {previewTitle} from "./../Preview";
|
|
||||||
|
|
||||||
const channel = getContext("channel");
|
const channel = getContext("channel");
|
||||||
export let schema;
|
export let schema;
|
||||||
export let record;
|
export let record;
|
||||||
export let isCreateMode;
|
export let isCreateMode;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="record-header">
|
<div class="record-header">
|
||||||
|
<a class="schema-name" href="{channel.lucentUrl}/content/{schema.name}"
|
||||||
<a
|
>{schema.label.toUpperCase()}</a
|
||||||
class="schema-name"
|
|
||||||
href="{channel.lucentUrl}/content/{schema.name}"
|
|
||||||
>{schema.label.toUpperCase()}</a
|
|
||||||
>
|
>
|
||||||
<span class="record-title">
|
<span class="record-title">
|
||||||
{#if !isCreateMode}
|
{#if !isCreateMode}
|
||||||
{previewTitle(channel.schemas, record)}
|
{record.data.name}
|
||||||
{:else}
|
{:else}
|
||||||
New Record
|
New Record
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
import { createEventDispatcher, getContext } from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import Preview from "../../files/Preview.svelte";
|
import Preview from "../../files/Preview.svelte";
|
||||||
import { previewTitle } from "./../Preview";
|
|
||||||
import { fileurl, htmlurl } from "../../files/imageserver.js";
|
|
||||||
import Status from "./../Status.svelte";
|
|
||||||
import Dropdown from "../../common/Dropdown.svelte";
|
import Dropdown from "../../common/Dropdown.svelte";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Icon from "../../common/Icon.svelte";
|
import Icon from "../../common/Icon.svelte";
|
||||||
|
|
||||||
import {createEventDispatcher, getContext} from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import {previewTitle} from "./../Preview";
|
|
||||||
import Status from "./../Status.svelte";
|
import Status from "./../Status.svelte";
|
||||||
import Preview from "../../files/Preview.svelte";
|
import Preview from "../../files/Preview.svelte";
|
||||||
|
|
||||||
@@ -12,10 +11,15 @@
|
|||||||
export let record;
|
export let record;
|
||||||
export let hasDelete = false;
|
export let hasDelete = false;
|
||||||
|
|
||||||
let schema = channel.schemas.find((aschema) => aschema.name === record.schema);
|
let schema = channel.schemas.find(
|
||||||
let cardTitle = previewTitle(channel.schemas, record, graph);
|
(aschema) => aschema.name === record.schema,
|
||||||
const cardImageEdge = graph.edges.find(e => e.source === record.id && e.field === schema.cardImage);
|
);
|
||||||
let cardImageRecord = graph.records.find(r => r.id === cardImageEdge?.target);
|
const cardImageEdge = graph.edges.find(
|
||||||
|
(e) => e.source === record.id && e.field === schema.cardImage,
|
||||||
|
);
|
||||||
|
let cardImageRecord = graph.records.find(
|
||||||
|
(r) => r.id === cardImageEdge?.target,
|
||||||
|
);
|
||||||
|
|
||||||
function remove(e) {
|
function remove(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -23,43 +27,35 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="preview-reference">
|
<div class="preview-reference">
|
||||||
<div style="display: flex;align-items: center;gap: 10px;">
|
<div style="display: flex;align-items: center;gap: 10px;">
|
||||||
|
|
||||||
{#if cardImageRecord}
|
{#if cardImageRecord}
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<Preview record={cardImageRecord} size="small"/>
|
<Preview record={cardImageRecord} size="small" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<div>
|
<div>
|
||||||
<a
|
<a
|
||||||
class="record-title"
|
class="record-title"
|
||||||
href="{channel.lucentUrl}/records/{record.id}"
|
href="{channel.lucentUrl}/records/{record.id}"
|
||||||
>
|
>
|
||||||
{cardTitle}
|
{record.data.name}
|
||||||
</a>
|
</a>
|
||||||
<small class="d-block">
|
<small class="d-block">
|
||||||
from {schema.label}
|
from {schema.label}
|
||||||
{#if record.status === "draft"}
|
{#if record.status === "draft"}
|
||||||
<Status status={record.status}/>
|
<Status status={record.status} />
|
||||||
{/if}
|
{/if}
|
||||||
</small>
|
</small>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if hasDelete}
|
{#if hasDelete}
|
||||||
<div class="reference-action">
|
<div class="reference-action">
|
||||||
<button
|
<button class="button" on:click={remove}>
|
||||||
class="button"
|
<Icon icon="trash-can" />
|
||||||
on:click={remove}
|
|
||||||
>
|
|
||||||
<Icon icon="trash-can"/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
"env" => env("LUCENT_ENV", "production"),
|
"env" => env("LUCENT_ENV", "production"),
|
||||||
|
// lucent or lunar
|
||||||
"auth" => env("LUCENT_AUTH", "lucent"),
|
"auth" => env("LUCENT_AUTH", "lucent"),
|
||||||
|
"disk" => env("LUCENT_DISK", "public"),
|
||||||
"schemas_path" => env("LUCENT_SCHEMAS_PATH", "resources/lucent/schemas"),
|
"schemas_path" => env("LUCENT_SCHEMAS_PATH", "resources/lucent/schemas"),
|
||||||
"database" => env("LUCENT_DB_CONNECTION", env("DB_CONNECTION", "sqlite")),
|
"database" => env("LUCENT_DB_CONNECTION", env("DB_CONNECTION", "sqlite")),
|
||||||
"name" => env("LUCENT_NAME", "Lucent"),
|
"name" => env("LUCENT_NAME", "Lucent"),
|
||||||
|
|||||||
@@ -16,10 +16,7 @@ class Schema
|
|||||||
public array $visible,
|
public array $visible,
|
||||||
public array $groups,
|
public array $groups,
|
||||||
public Collection $fields,
|
public Collection $fields,
|
||||||
public bool $isEntry = false,
|
|
||||||
public string $color = "",
|
|
||||||
public string $sortBy = "-_sys.updatedAt",
|
public string $sortBy = "-_sys.updatedAt",
|
||||||
public ?string $cardTitle = null,
|
|
||||||
public ?string $cardImage = null,
|
public ?string $cardImage = null,
|
||||||
public int $revisions = 0,
|
public int $revisions = 0,
|
||||||
public array $read = [],
|
public array $read = [],
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use Lucent\Schema\System;
|
|||||||
use Lucent\Schema\Ui\Reference;
|
use Lucent\Schema\Ui\Reference;
|
||||||
use Lucent\Schema\Validator\ValidatorException;
|
use Lucent\Schema\Validator\ValidatorException;
|
||||||
use Lucent\Svelte\Svelte;
|
use Lucent\Svelte\Svelte;
|
||||||
use Lucent\ViewModel\ViewModel;
|
|
||||||
use function Lucent\Response\fail;
|
use function Lucent\Response\fail;
|
||||||
use function Lucent\Response\ok;
|
use function Lucent\Response\ok;
|
||||||
|
|
||||||
@@ -36,7 +35,6 @@ class RecordController extends Controller
|
|||||||
private readonly Query $query,
|
private readonly Query $query,
|
||||||
private readonly Manager $recordManager,
|
private readonly Manager $recordManager,
|
||||||
private readonly OperatorRegistry $operatorRegistry,
|
private readonly OperatorRegistry $operatorRegistry,
|
||||||
private readonly ViewModel $viewModel,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
@@ -217,7 +215,7 @@ class RecordController extends Controller
|
|||||||
$c[] = "";
|
$c[] = "";
|
||||||
} elseif (count($fieldRecords) === 1) {
|
} elseif (count($fieldRecords) === 1) {
|
||||||
$c[] = data_get($fieldRecords, "0.id");
|
$c[] = data_get($fieldRecords, "0.id");
|
||||||
$c[] = $this->viewModel->getRecordName($fieldRecords[0]);
|
$c[] = $fieldRecords[0]->data["name"];
|
||||||
} else {
|
} else {
|
||||||
$c[] = collect($fieldRecords)->pluck("id")->join("::");
|
$c[] = collect($fieldRecords)->pluck("id")->join("::");
|
||||||
$c[] = collect($fieldRecords)
|
$c[] = collect($fieldRecords)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use Illuminate\Support\Facades\View;
|
|||||||
use Lucent\Account\AccountService;
|
use Lucent\Account\AccountService;
|
||||||
use Lucent\Account\AuthService;
|
use Lucent\Account\AuthService;
|
||||||
use Lucent\Channel\ChannelService;
|
use Lucent\Channel\ChannelService;
|
||||||
use Lucent\ViewModel\ViewModel;
|
|
||||||
|
|
||||||
readonly class AuthMiddleware
|
readonly class AuthMiddleware
|
||||||
{
|
{
|
||||||
@@ -16,7 +15,6 @@ readonly class AuthMiddleware
|
|||||||
private AuthService $authService,
|
private AuthService $authService,
|
||||||
private AccountService $accountService,
|
private AccountService $accountService,
|
||||||
private ChannelService $channelService,
|
private ChannelService $channelService,
|
||||||
private ViewModel $viewModel,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
@@ -38,7 +36,6 @@ readonly class AuthMiddleware
|
|||||||
)
|
)
|
||||||
->values(),
|
->values(),
|
||||||
);
|
);
|
||||||
View::share("viewModel", $this->viewModel);
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Schema;
|
|
||||||
|
|
||||||
use Lucent\Primitive\Collection;
|
|
||||||
|
|
||||||
class CollectionSchema implements Schema
|
|
||||||
{
|
|
||||||
public Type $type = Type::COLLECTION;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collection<FieldInterface> $fields
|
|
||||||
* @param array<string> $visible
|
|
||||||
*/
|
|
||||||
function __construct(
|
|
||||||
public string $name,
|
|
||||||
public string $label,
|
|
||||||
public array $visible,
|
|
||||||
public array $groups,
|
|
||||||
public Collection $fields,
|
|
||||||
public bool $isEntry = false,
|
|
||||||
public string $color = "",
|
|
||||||
public string $sortBy = "-_sys.updatedAt",
|
|
||||||
public ?string $cardTitle = null,
|
|
||||||
public ?string $cardImage = null,
|
|
||||||
public int $revisions = 0,
|
|
||||||
public array $read = [],
|
|
||||||
public array $write = [],
|
|
||||||
)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Schema;
|
|
||||||
|
|
||||||
use Lucent\Primitive\Collection;
|
|
||||||
|
|
||||||
class FilesSchema implements Schema
|
|
||||||
{
|
|
||||||
|
|
||||||
public Type $type = Type::FILES;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collection<FieldInterface> $fields
|
|
||||||
* @param array<string> $groups
|
|
||||||
*/
|
|
||||||
function __construct(
|
|
||||||
public string $name,
|
|
||||||
public string $label,
|
|
||||||
public Collection $fields,
|
|
||||||
public string $disk,
|
|
||||||
public string $path,
|
|
||||||
public array $groups,
|
|
||||||
public bool $isEntry = false,
|
|
||||||
public string $sortBy = "-_sys.updatedAt",
|
|
||||||
public string $color = "",
|
|
||||||
public ?string $cardTitle = null,
|
|
||||||
public ?string $cardImage = null,
|
|
||||||
public int $revisions = 0,
|
|
||||||
public array $read = [],
|
|
||||||
public array $write = [],
|
|
||||||
)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\Schema;
|
|
||||||
|
|
||||||
interface Schema
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -31,11 +31,7 @@ class SchemaService
|
|||||||
$this,
|
$this,
|
||||||
"mapFields",
|
"mapFields",
|
||||||
]),
|
]),
|
||||||
isEntry: $schemaArr["isEntry"] ?? false,
|
|
||||||
color: $schemaArr["color"] ?? "",
|
|
||||||
sortBy: $schemaArr["sortBy"] ?? "-_sys.updatedAt",
|
sortBy: $schemaArr["sortBy"] ?? "-_sys.updatedAt",
|
||||||
cardTitle: $schemaArr["titleTemplate"] ??
|
|
||||||
($schemaArr["cardTitle"] ?? null),
|
|
||||||
cardImage: $schemaArr["cardImage"] ?? null,
|
cardImage: $schemaArr["cardImage"] ?? null,
|
||||||
revisions: $schemaArr["revisions"] ?? 0,
|
revisions: $schemaArr["revisions"] ?? 0,
|
||||||
read: $schemaArr["read"] ?? [],
|
read: $schemaArr["read"] ?? [],
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class Slug implements FieldInterface, RequiredInterface
|
|||||||
$value = Str::slug($input[$this->source]);
|
$value = Str::slug($input[$this->source]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$output[$this->name] = new Nullable(
|
$output[$this->name] = Nullable::make(
|
||||||
$this->nullable,
|
$this->nullable,
|
||||||
$value,
|
$value,
|
||||||
"",
|
"",
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Lucent\ViewModel;
|
|
||||||
|
|
||||||
use Lucent\Channel\ChannelService;
|
|
||||||
use Lucent\Record\QueryRecord;
|
|
||||||
use Lucent\Schema\CollectionSchema;
|
|
||||||
use Lucent\Schema\FieldInterface;
|
|
||||||
use Lucent\Schema\FilesSchema;
|
|
||||||
use Mustache_Engine;
|
|
||||||
|
|
||||||
class ViewModel
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
public ChannelService $channelService
|
|
||||||
)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function getRecordName(QueryRecord $record): string
|
|
||||||
{
|
|
||||||
$schema = $this->channelService->getSchema($record->schema)->get();
|
|
||||||
if (empty($schema->cardTitle)) {
|
|
||||||
$title = match (get_class($schema)) {
|
|
||||||
CollectionSchema::class => $record->data[$schema->fields->filter(fn(FieldInterface $f) => $f->info->name === "text")->first()->name],
|
|
||||||
FilesSchema::class => $record->_file->path,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (empty(trim($title))) {
|
|
||||||
return "~Untitled~";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $title;
|
|
||||||
}
|
|
||||||
|
|
||||||
$m = new Mustache_Engine(array('entity_flags' => ENT_QUOTES));
|
|
||||||
return $m->render($schema->cardTitle, $record->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user