tags ui
This commit is contained in:
@@ -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}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user