This commit is contained in:
2023-10-07 21:18:18 +03:00
parent f2faec67fe
commit 956b8dc4e3
12 changed files with 378 additions and 113 deletions
@@ -1,12 +1,15 @@
<script>
import { createEventDispatcher } from "svelte";
import {createEventDispatcher, getContext} from "svelte";
import Icon from "../../common/Icon.svelte";
import InlineEdit from "../InlineEdit.svelte";
import BrowseModal from "./BrowseModal.svelte";
const dispatch = createEventDispatcher();
// export let field;
// export let buttonLabel = "";
// export let buttonClass = "";
const channel = getContext("channel");
export let schemas;
export let recordId;
$: showOptions = false;
@@ -41,7 +44,7 @@
function createInlineReference(e, schemaUId) {
e.preventDefault();
axios
.get("/records/newInline?schema=" + schemaUId)
.get(channel.lucentUrl + "/records/newInline?schema=" + schemaUId)
.then((response) => {
inLineCreateRecord = response.data;
showOptions = false;
@@ -54,34 +57,36 @@
{#if schemas.length > 1}
<button
type="button"
class:is-first={!recordId}
class=" btn btn-lg btn-link text-decoration-none inline-card-button"
on:click|preventDefault={(e) => (showOptions = !showOptions)}
type="button"
class:is-first={!recordId}
class=" btn btn-lg btn-link text-decoration-none inline-card-button"
on:click|preventDefault={(e) => (showOptions = !showOptions)}
>
<Icon width={24} height={24} icon="circle-plus" />
<Icon width={24} height={24} icon="circle-plus"/>
</button>
{#if showOptions}
<div class="bg-light lx-card d-flex">
{#each schemas as schema}
<div
class="lx-card p-4 text-center me-4"
style="max-width: 250px;"
class="lx-card p-4 text-center me-4"
style="max-width: 250px;"
>
<p>{schema.label}</p>
<div class="mb-2">
<button
class="btn btn-sm btn-primary"
on:click={(e) =>
class="btn btn-sm btn-primary"
on:click={(e) =>
createInlineReference(e, schema.name)}
>New
>New
</button>
<button
class="btn btn-sm btn-outline-primary"
on:click={(e) => openBrowseModal(e, schema.name)}
><Icon icon="magnifying-glass" /></button
class="btn btn-sm btn-outline-primary"
on:click={(e) => openBrowseModal(e, schema.name)}
>
<Icon icon="magnifying-glass"/>
</button
>
</div>
</div>
@@ -92,14 +97,16 @@
<div class="pb-2 text-start">
<div class="mb-2">
<button
class="btn btn-sm btn-primary"
on:click={(e) => createInlineReference(e, schemas[0].name)}
>New
class="btn btn-sm btn-primary"
on:click={(e) => createInlineReference(e, schemas[0].name)}
>New
</button>
<button
class="btn btn-sm btn-outline-primary"
on:click={(e) => openBrowseModal(e, schemas[0].name)}
><Icon icon="magnifying-glass" /></button
class="btn btn-sm btn-outline-primary"
on:click={(e) => openBrowseModal(e, schemas[0].name)}
>
<Icon icon="magnifying-glass"/>
</button
>
</div>
</div>
@@ -107,25 +114,28 @@
{#if inLineCreateRecord}
<InlineEdit
{...inLineCreateRecord}
on:cancel={(e) => (inLineCreateRecord = null)}
on:inlinesaved={save}
{...inLineCreateRecord}
on:cancel={(e) => (inLineCreateRecord = null)}
on:inlinesaved={save}
/>
{/if}
<BrowseModal bind:this={browseModal} on:insert={insert} />
<BrowseModal bind:this={browseModal} on:insert={insert}/>
<style>
:global(.inline-card-wrapper) {
display: flex;
flex-direction: column;
}
:global(.inline-card-wrapper .inline-card-button) {
visibility: hidden;
}
:global(.inline-card-wrapper .inline-card-button.is-first) {
visibility: visible;
}
:global(.inline-card-wrapper:hover .inline-card-button) {
visibility: visible;
}
@@ -0,0 +1,179 @@
<script>
import {getContext} from "svelte";
import {uniqBy, debounce} from "lodash";
import {previewTitle} from "../Preview";
import {getErrorMessage} from "./errorMessage";
import {sortByField} from "../../edges/sortEdges";
import ReferenceInlineButtons from "./ReferenceInlineButtons.svelte";
import Sortable from "../../libs/Sortable.svelte";
import RenderField from "../../content/RenderField.svelte";
import Icon from "../../common/Icon.svelte";
import Datalist from "./Datalist.svelte";
const channel = getContext("channel");
export let field;
export let id;
export let record;
export let graph;
export let validationErrors;
$: errorMessage = getErrorMessage(validationErrors, field.name);
$: references = graph.edges
.filter((edge) => edge.field === field.name)
.map((edge) => {
return graph.records.find((increc) => increc.id == edge.target && record.id == edge.source);
}).filter((rec) => (rec?.id ? true : false)) ?? [];
let search = ""
$: searchOptions = []
function removeReference(e, recordId) {
e.preventDefault();
graph.edges = graph.edges.filter(
(edge) => !(edge.target === recordId && edge.field === field.name)
);
}
function saveNew(e, newValue) {
e.preventDefault();
axios
.post(channel.lucentUrl + "/records", {
isCreateMode: true,
record: {
schema: field.collections[0],
status: "published",
data: {
[field.searchField]: newValue
}
},
})
.then((response) => {
searchOptions = [];
insert(e,response.data.records[0]);
console.log(response)
})
.catch((error) => {
searchOptions = [];
console.log(error);
});
}
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);
}
const updateResults = debounce((e) => {
axios
.get(channel.lucentUrl + "/records/suggestions", {
params: {
schema: field.collections[0],
field: field.searchField,
value: search,
ui: "text",
},
})
.then((response) => {
searchOptions = response.data;
})
.catch((error) => {
searchOptions = [];
console.log(error);
});
}, 500);
</script>
{#if errorMessage}
<div class="invalid-feedback d-block mb-3">
{errorMessage}
</div>
{/if}
<input
type="search"
{id}
on:keyup={updateResults}
class="form-control dropdown-toggle"
class:is-invalid={errorMessage}
bind:value={search}
placeholder={"Search for "+field.label}
data-bs-toggle="dropdown"
autocomplete="off"
readonly={field.readonly && !isCreateMode}
/>
<div class="dropdown-menu w-100">
{#if searchOptions}
{#each searchOptions as option (option.id)}
<div
on:click={(e) => insert(e, option)}
on:keypress={(e) => insert(e, option)}
>
<span class="dropdown-item">
{previewTitle(channel.schemas, option)}
</span>
</div>
{:else}
Start typing...
{/each}
{/if}
{#if search }
<div
on:click={(e) => saveNew(e,search)}
on:keypress={(e) => saveNew(e,search)}
>
<span class="dropdown-item">
Add "{search}"
</span>
</div>
{/if}
</div>
{#if references.length > 0}
<div class="d-flex">
{#each references as record (record.id)}
<span class="badge rounded-pill bg-light text-dark fs-6 mt-3">
<div class="d-flex align-items-center ">
{previewTitle(channel.schemas, record)}
<button
on:click|preventDefault={(e) => removeReference(e, record.id)}
type="button"
class="btn-close btn-sm ms-1"
style="font-size:10px"
aria-label="Close"
/>
</div>
</span>
{/each}
</div>
{/if}