This commit is contained in:
2023-10-13 21:06:23 +03:00
parent 129e3af471
commit 9e37a7f730
34 changed files with 845 additions and 780 deletions
+2 -2
View File
@@ -51,13 +51,13 @@
<ReferenceInline
bind:graph
{record}
{schema}
{field}
{validationErrors}
/>
{:else if field.info.name === "reference" && field.layout === "table"}
<ReferenceTable
bind:graph
{id}
{record}
{field}
{validationErrors}
@@ -73,8 +73,8 @@
{:else if field.info.name === "reference"}
<Reference
bind:graph
{id}
{record}
{schema}
{field}
{validationErrors}
/>
+3 -4
View File
@@ -8,9 +8,8 @@
const channel = getContext("channel");
export let graph;
export let record;
let parentEdgesByField = graph.edges
.filter((edge) => edge.source !== record.id && edge.depth === 0)
let parentEdgesByField = graph.parentEdges
.filter((edge) => edge.source !== record.id && edge.depth === 1)
.reduce((carry, edge) => {
let schemaField = edge.sourceSchema + edge.field;
@@ -32,7 +31,7 @@
}
return carry;
}, {});
console.log(parentEdgesByField)
let childrenEdgesByField = graph.edges
.filter((edge) => edge.source === record.id && edge.depth === 0)
.reduce((carry, edge) => {
+28 -29
View File
@@ -1,5 +1,5 @@
<script>
import {afterUpdate, createEventDispatcher, onMount,} from "svelte";
import {afterUpdate, createEventDispatcher, onMount,getContext} from "svelte";
import {isEqual} from "lodash";
import FormField from "./FormField.svelte";
@@ -8,9 +8,9 @@
import StatusSelect from "./StatusSelect.svelte";
import ErrorAlert from "../common/ErrorAlert.svelte";
const channel = getContext("channel");
const dispatch = createEventDispatcher();
export let schema;
export let schemas;
export let record;
export let graph = {
records: [],
@@ -18,7 +18,7 @@
};
export let isCreateMode;
let originalContent;
let activeContentTab = "_default";
let activeContentTab = "";
let hasUnsavedData = false;
$: validationErrors = null;
$: errorMessage = validationErrors
@@ -28,7 +28,7 @@
: null;
let activeFields = schema.fields.filter(
(f) => f.trashed === false && f.name !== "id"
(f) => f.name !== "id"
);
let tabname = "_default";
@@ -116,7 +116,7 @@
axios
.post("/records", {
.post(channel.lucentUrl + "/records", {
record: record,
edges: graph.edges,
isCreateMode: isCreateMode,
@@ -159,24 +159,23 @@
<div class=" mt-1">
<ContentTabs
{schema}
{isCreateMode}
bind:active={activeContentTab}
{record}
{schema}
{isCreateMode}
bind:active={activeContentTab}
{record}
/>
<FilePreview {record} {schema}/>
<!-- <fieldset disabled="disabled"> -->
{#each activeFields as field (field.name)}
{#if fieldToTabs[activeContentTab].includes(field.name)}
{#if activeContentTab === field.group}
<FormField
bind:data={record.data}
bind:graph={graph}
{field}
{schema}
{schemas}
{record}
{validationErrors}
{isCreateMode}
bind:data={record.data}
bind:graph={graph}
{field}
{schema}
{record}
{validationErrors}
{isCreateMode}
/>
{/if}
{/each}
@@ -189,26 +188,26 @@
{/if}
{#if isCreateMode}
<button
class="ms-2 btn btn-primary btn-spinner"
on:click={save}
class="ms-2 btn btn-primary btn-spinner"
on:click={save}
>
<span
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
/>
Add
</button>
{:else}
<button
disabled={!hasUnsavedData}
class="ms-2 btn btn-primary btn-spinner"
on:click={save}
disabled={!hasUnsavedData}
class="ms-2 btn btn-primary btn-spinner"
on:click={save}
>
<span
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
/>
Save
</button>
+1 -4
View File
@@ -63,10 +63,7 @@
</div>
<style>
.button-file {
width: 64px;
height: 65px;
}
.card .trash-button {
display: none;
}
@@ -2,30 +2,32 @@
import Icon from "../common/Icon.svelte";
import {createEventDispatcher, onMount} from "svelte";
import {createEventDispatcher, onMount, getContext} from "svelte";
import Preview from "../files/Preview.svelte";
import InlineEdit from "./InlineEdit.svelte";
import Reference from "../content/elements/Reference.svelte";
import File from "../content/elements/File.svelte";
const channel = getContext("channel");
const dispatch = createEventDispatcher();
export let isFirst;
export let isLast;
export let toDelete = false;
export let schemas;
export let record;
let editRecord;
let schema = schemas.find((aschema) => aschema.name === record.schema);
let editGraph;
let schema = channel.schemas.find((aschema) => aschema.name === record.schema);
$: editMode = false;
$: expanded = false;
function editInline(e) {
e.preventDefault();
axios
.get("/records/editInline/" + record.id)
.get(channel.lucentUrl + "/records/editInline/" + record.id)
.then((response) => {
record = response.data;
editRecord = response.data;
editRecord = response.data.record;
editGraph = response.data.graph;
editMode = true;
})
.catch((error) => {
@@ -76,7 +78,7 @@
function deleteFromChannel(e) {
e.preventDefault();
axios
.post("/records/status/trashed", [record])
.post(channel.lucentUrl +"/records/status/trashed", [record])
.then((response) => {
dispatch("remove", record.id);
})
@@ -92,13 +94,13 @@
<p>Item was removed from the current record.</p>
<p>
<button
class="btn btn-sm btn-outline border border-1 border-dark"
on:click={undo}>Undo
class="btn btn-sm btn-outline border border-1 border-dark"
on:click={undo}>Undo
</button
>
<button
class="btn btn-sm btn-danger "
on:click={deleteFromChannel}
class="btn btn-sm btn-danger "
on:click={deleteFromChannel}
>Delete completely from channel
</button
>
@@ -110,26 +112,26 @@
</div>
{:else if editMode === true}
<InlineEdit
{schema}
{schemas}
record={editRecord}
isCreateMode={false}
on:cancel={cancel}
on:inlinesaved={handleInlinesaved}
{schema}
record={editRecord}
graph={editGraph}
isCreateMode={false}
on:cancel={cancel}
on:inlinesaved={handleInlinesaved}
/>
{:else}
<div class="lx-card mt-4 bg-primary bg-opacity-10">
<div class="actions">
<small class="text-muted">{schema.label}</small>
<button
class="btn btn-sm btn-link"
on:click|preventDefault={editInline}
class="btn btn-sm btn-link"
on:click|preventDefault={editInline}
>
<Icon icon="pencil" width={12} height={12}/>
</button>
<button
class="btn btn-sm btn-link"
on:click={(e) => (expanded = !expanded)}
class="btn btn-sm btn-link"
on:click={(e) => (expanded = !expanded)}
>
{#if expanded}
<Icon icon="compress" width={12} height={12}/>
@@ -139,19 +141,19 @@
</button>
<div class="dropdown d-inline-block">
<button
class="btn btn-link btn-sm"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
class="btn btn-link btn-sm"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<Icon icon="ellipsis"/>
</button>
<div class="dropdown-menu">
<a
class="dropdown-item"
href="/records/{record.id}"
target="_blank"
class="dropdown-item"
href="/records/{record.id}"
target="_blank"
>Edit in new tab
</a>
<button class="dropdown-item" on:click={trash}>
@@ -162,16 +164,16 @@
{#if !isFirst}
<button
class="btn btn-sm btn-outline-primary border-0"
on:click|preventDefault={moveup}
class="btn btn-sm btn-outline-primary border-0"
on:click|preventDefault={moveup}
>
<Icon icon="circle-chevron-up"/>
</button>
{/if}
{#if !isLast}
<button
class="btn btn-sm btn-outline-primary border-0"
on:click|preventDefault={movedn}
class="btn btn-sm btn-outline-primary border-0"
on:click|preventDefault={movedn}
>
<Icon icon="circle-chevron-down"/>
</button>
@@ -189,7 +191,7 @@
>{field.label}</span
>
{#if field.ui === "reference"}
<Reference {record} {schemas} {field}/>
<Reference {record} {field}/>
{:else if field.ui === "file"}
<File {record} {field}/>
{:else}
-113
View File
@@ -1,113 +0,0 @@
<script>
import Mustache from "mustache";
import { imgurl } from "../files/imageserver";
import { uniqBy } from "lodash";
import { onMount, getContext } from "svelte";
import { Network } from "vis-network/esnext";
import "vis-network/styles/vis-network.css";
const channelurl = getContext("channelurl");
export let schemas;
export let recordGraph;
let network;
let allEdges = recordGraph._graph.edges.map((e) => {
e.fieldLabel = schemas
.find((s) => s.uid === e.fromSchema)
.fields.find((f) => f.name === e.field).label;
return e;
});
let nodes = recordGraph._graph.nodes.map((r) => {
let nodeOptions = {
id: r.data.id,
label: renderTitle(
schemas.find((s) => s.uid === r._sys.schema),
r
),
borderWidth: 0,
color: {
background:
r.data.id === recordGraph.data.id ? "#0b5d1e" : "#eeeeee",
},
font: {
multi: true,
color: r.data.id === recordGraph.data.id ? "#fff" : "#333",
},
};
nodeOptions.shape = "box";
if (r._file?.path) {
nodeOptions.shape = "image";
nodeOptions.image = imgurl(r, 64, 64, "crop");
}
return nodeOptions;
});
nodes = uniqBy(nodes, (n) => n.id);
// create an array with edges
let networkEdges = allEdges.map((e) => {
return {
from: e.from,
to: e.to,
label: e.fieldLabel,
arrows: {
to: {
enabled: true,
type: "arrow",
scaleFactor: 0.5,
},
},
font: { align: "middle" },
};
});
let data = {
nodes: nodes,
edges: networkEdges,
};
let options = {
physics: false,
layout: {
hierarchical: {
enabled: true,
nodeSpacing: 150,
treeSpacing: 200,
direction: "UD",
sortMethod: "directed",
},
},
};
onMount(() => {
let networkInstance = new Network(network, data, options);
networkInstance.on("doubleClick", function (params) {
if (params.nodes[0]) {
window.location = channelurl + "/records/" + params.nodes[0];
}
});
});
function renderTitle(schema, record) {
const template = `${schema.titleTemplate}\n <i>${schema.label}</i>`;
Mustache.parse(template);
let recordData = { ...record, ...record.data };
return Mustache.render(template, recordData);
}
</script>
<div class="lx-card">
<div class="network-container" bind:this={network} />
</div>
<style>
.network-container {
width: 100%;
height: 80vh;
max-height: 800px;
}
</style>
@@ -1,6 +1,6 @@
<script>
import {getContext} from "svelte";
import {uniqBy} from "lodash";
import {insertEdges} from "./reference";
import PreviewCard from "../PreviewCard.svelte";
import {getErrorMessage} from "./errorMessage";
import {sortByField} from "../../edges/sortEdges";
@@ -37,26 +37,7 @@
function insert(e) {
e.preventDefault();
const recordsToInsert = e.detail.records;
const action = e.detail.action;
let newEdges = recordsToInsert.map((r) => {
return {
target: r.id,
source: record.id,
sourceSchema: record.schema,
targetSchema: r.schema,
field: field.name,
rank: ""
};
});
let replacedEdges = graph.edges;
if (action === "replace") {
replacedEdges = replacedEdges.filter((edge) => edge.field !== field.name);
}
graph.records = uniqBy([...graph.records, ...recordsToInsert], (r) => r.id);
graph.edges = uniqBy([...replacedEdges, ...newEdges], (edge) => edge.target + edge.field);
graph = insertEdges(graph,record,e.detail.records,field.name,e.detail.action);
}
</script>
@@ -68,7 +49,6 @@
{/if}
<div class="inline-card-wrapper">
<ReferenceInlineButtons
{field}
buttonClass="mt-2"
recordId={null}
schemas={collections}
@@ -1,6 +1,5 @@
<script>
import {getContext} from "svelte";
import {uniqBy} from "lodash";
import {previewTitle} from "../Preview";
import {getErrorMessage} from "./errorMessage";
import {sortByField} from "../../edges/sortEdges";
@@ -8,10 +7,10 @@
import Sortable from "../../libs/Sortable.svelte";
import RenderField from "../../content/RenderField.svelte";
import Icon from "../../common/Icon.svelte";
import {insertEdges} from "./reference.js";
const channel = getContext("channel");
export let field;
export let record;
export let graph;
export let validationErrors;
@@ -46,26 +45,8 @@
function insert(e) {
e.preventDefault();
const recordsToInsert = e.detail.records;
const action = e.detail.action;
let newEdges = recordsToInsert.map((r) => {
return {
target: r.id,
source: record.id,
sourceSchema: record.schema,
targetSchema: r.schema,
field: field.name,
rank: ""
};
});
let replacedEdges = graph.edges;
if (action === "replace") {
replacedEdges = replacedEdges.filter((edge) => edge.field !== field.name);
}
graph.records = uniqBy([...graph.records, ...recordsToInsert], (r) => r.id);
graph.edges = uniqBy([...replacedEdges, ...newEdges], (edge) => edge.target + edge.field);
graph = insertEdges(graph,record,e.detail.records,field.name,e.detail.action);
console.log(graph)
}
$:visibleColumns = [];
@@ -118,7 +99,7 @@
<div class="d-flex align-items-center">
<a
class="me-2 text-decoration-none text-dark fs-6"
href="/records/{record.id}"
href="{channel.lucentUrl}/records/{record.id}"
target="_blank"
>
{previewTitle(channel.schemas, record)}
@@ -9,6 +9,7 @@
import RenderField from "../../content/RenderField.svelte";
import Icon from "../../common/Icon.svelte";
import Datalist from "./Datalist.svelte";
import {insertEdges} from "./reference.js";
const channel = getContext("channel");
export let field;
@@ -62,26 +63,7 @@
function insert(e, insertRecord) {
e.preventDefault();
const recordsToInsert = [insertRecord];
const action = e.detail.action;
let newEdges = recordsToInsert.map((r) => {
return {
target: r.id,
source: record.id,
sourceSchema: record.schema,
targetSchema: r.schema,
field: field.name,
rank: ""
};
});
let replacedEdges = graph.edges;
if (action === "replace") {
replacedEdges = replacedEdges.filter((edge) => edge.field !== field.name);
}
graph.records = uniqBy([...graph.records, ...recordsToInsert], (r) => r.id);
graph.edges = uniqBy([...replacedEdges, ...newEdges], (edge) => edge.target + edge.field);
graph = insertEdges(graph,record,[insertRecord],field.name,e.detail.action);
}
const updateResults = debounce((e) => {
@@ -2,22 +2,38 @@
export let field;
export let value;
export let search;
function select(e, option) {
function select(e, option) {
e.preventDefault();
value = option;
search = "";
}
</script>
{#if field.selectOptions}
{#each field.selectOptions as suggestion (suggestion)}
<div
on:click={(e) => select(e, suggestion)}
on:keypress={(e) => select(e, suggestion)}
>
{#if Array.isArray(field.selectOptions)}
{#each field.selectOptions as suggestion (suggestion)}
<div
on:click={(e) => select(e, suggestion)}
on:keypress={(e) => select(e, suggestion)}
>
<span class="dropdown-item">
{suggestion}
</span>
</div>
{/each}
</div>
{/each}
{:else}
{#each Object.entries(field.selectOptions) as [k, v] (k)}
<div
on:click={(e) => select(e, k)}
on:keypress={(e) => select(e, k)}
>
<span class="dropdown-item">
{v}
</span>
</div>
{/each}
{/if}
{/if}
+6 -2
View File
@@ -75,7 +75,6 @@
autocomplete="off"
readonly={field.readonly && !isCreateMode}
/>
<div class="dropdown-menu w-100">
<Selectlist
{field}
@@ -87,7 +86,12 @@
{#if value}
<span class="badge rounded-pill bg-light text-dark fs-6 mt-3">
<div class="d-flex align-items-center ">
{value}
{#if Array.isArray(field.selectOptions)}
{value}
{:else}
{field.selectOptions[value]}
{/if}
<button
on:click|preventDefault={(e) => (value = "")}
type="button"
@@ -0,0 +1,23 @@
import {uniqBy} from "lodash";
export function insertEdges(graph, sourceRecord, targetRecords, fieldName, action = "") {
let newEdges = targetRecords.map((r) => {
return {
target: r.id,
source: sourceRecord.id,
sourceSchema: sourceRecord.schema,
targetSchema: r.schema,
field: fieldName,
rank: ""
};
});
let replacedEdges = graph.edges;
if (action === "replace") {
replacedEdges = replacedEdges.filter((edge) => edge.field !== field.name);
}
graph.records = uniqBy([...graph.records, ...targetRecords], (r) => r.id);
graph.edges = uniqBy([...replacedEdges, ...newEdges], (edge) => edge.source + edge.target + edge.field);
return graph;
}