references

This commit is contained in:
2024-08-16 16:00:48 +03:00
parent a04e338ce2
commit 9bbd53b586
20 changed files with 170 additions and 90 deletions
@@ -1,6 +1,7 @@
<script> <script>
import {createEventDispatcher, getContext} from "svelte"; import {createEventDispatcher, getContext} from "svelte";
import {previewTitle} from "../../records/Preview"; import {previewTitle} from "../../records/Preview";
import Icon from "../../common/Icon.svelte";
const channel = getContext("channel"); const channel = getContext("channel");
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@@ -73,8 +74,8 @@
} }
</script> </script>
<span class="applied-filter d-inline-block border border-primary rounded lx-small-text me-1 px-2 py-1"> <span class="applied-filter">
<div class="d-flex align-items-center justify-content-center">
{#if filter.isReference && filterRecord} {#if filter.isReference && filterRecord}
{filter.label} is {previewTitle(channel.schemas, filterRecord)} {filter.label} is {previewTitle(channel.schemas, filterRecord)}
{:else} {:else}
@@ -83,20 +84,9 @@
<button <button
on:click|preventDefault={() => removeFilter(key)} on:click|preventDefault={() => removeFilter(key)}
type="button" type="button"
class="btn-close btn-close ms-1" class="button-text"
aria-label="Close" aria-label="Close"
/> ><Icon width={12} height={12} icon="close"></Icon></button>
</div>
</span> </span>
<style>
.applied-filter {
background-color: #fff;
line-height: 22px;
}
.applied-filter:hover {
opacity: .8;
background-color: #eee;
}
</style>
+1 -1
View File
@@ -130,7 +130,7 @@
{#if Object.entries(filter).length > 0} {#if Object.entries(filter).length > 0}
<div class=" d-flex mb-3"> <div class="applied-filters">
{#each Object.entries(filter) as [k, v]} {#each Object.entries(filter) as [k, v]}
<AppliedFilter <AppliedFilter
{schema} {schema}
+3 -1
View File
@@ -83,7 +83,7 @@
{selectedRecords.length} records selected {selectedRecords.length} records selected
</span> </span>
{/if} {/if}
</div>
<button <button
on:click|preventDefault={close} on:click|preventDefault={close}
type="button" type="button"
@@ -92,6 +92,8 @@
> >
<Icon icon="close"></Icon> <Icon icon="close"></Icon>
</button> </button>
</div>
<div class="dialog-body"> <div class="dialog-body">
<Index {...data} bind:selected={selectedRecords}></Index> <Index {...data} bind:selected={selectedRecords}></Index>
</div> </div>
+2 -5
View File
@@ -1,22 +1,19 @@
<script> <script>
import NavbarMenu from "./NavbarMenu.svelte"; import NavbarMenu from "./NavbarMenu.svelte";
import {getContext} from "svelte"; import {getContext} from "svelte";
import Avatar from "../account/Avatar.svelte";
export let schema; export let schema;
const channel = getContext("channel"); const channel = getContext("channel");
const readableSchemas = getContext("readableSchemas"); const readableSchemas = getContext("readableSchemas");
const user = getContext("user");
const fileSchemas = readableSchemas.filter((sc) => sc.type === "files"); const fileSchemas = readableSchemas.filter((sc) => sc.type === "files");
const otherSchemas = readableSchemas.filter((sc) => !sc.isEntry && sc.type === "collection"); const otherSchemas = readableSchemas.filter((sc) => !sc.isEntry && sc.type === "collection");
</script> </script>
<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 class="nav-item" href="{channel.lucentUrl}/profile">
<Avatar side="28" name={user.name}/> </a>
</a>
</div> </div>
<div class="sidebar"> <div class="sidebar">
+2 -2
View File
@@ -17,14 +17,14 @@
} }
</script> </script>
<div class="sidebar-header" role="button" tabindex="0" on:click={toggleExpand}> <button class="sidebar-header" tabindex="0" on:click={toggleExpand}>
{title} {title}
{#if expanded} {#if expanded}
<Icon icon="circle-chevron-up"></Icon> <Icon icon="circle-chevron-up"></Icon>
{:else} {:else}
<Icon icon="circle-chevron-down"></Icon> <Icon icon="circle-chevron-down"></Icon>
{/if} {/if}
</div> </button>
{#if expanded} {#if expanded}
{#each schemas as aschema} {#each schemas as aschema}
<a class="sidebar-item" class:active={aschema.name === schema?.name} <a class="sidebar-item" class:active={aschema.name === schema?.name}
+10 -30
View File
@@ -1,6 +1,7 @@
<script> <script>
import Sortable from "sortablejs"; import Sortable from "sortablejs";
import { onMount, createEventDispatcher } from "svelte"; import {createEventDispatcher, onMount} from "svelte";
export let sortableClass = ""; export let sortableClass = "";
// export let handle; // export let handle;
export let isTable = false; export let isTable = false;
@@ -10,50 +11,29 @@
onMount(() => { onMount(() => {
let options = { let options = {
// handle: ".sortable-handle",
// draggable: ".quote-line-wrapper",
// filter: ".not-draggable", // Selectors that do not lead to dragging (String or Function)
// preventOnFilter: true,
animation: 150, // ms, animation speed moving items when sorting, `0` — without animation animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
easing: "cubic-bezier(1, 0, 0, 1)", easing: "cubic-bezier(1, 0, 0, 1)",
direction: 'vertical',
onUpdate: function (/**Event*/ evt) { onUpdate: function (/**Event*/ evt) {
// reorder(evt.oldIndex,evt.newIndex);
// console.log(evt)
dispatch("update", { dispatch("update", {
source: evt.oldIndex, source: evt.oldIndex,
target: evt.newIndex, target: evt.newIndex,
}); });
}, }
onMove(event) {
// if (event.related.className.indexOf("not-draggable") > -1) {
// return false;
// }
},
}; };
// if (handle) {
// options.handle = handle;
// }
sortableInstance = Sortable.create(sortableContainer, options); sortableInstance = Sortable.create(sortableContainer, options);
}); });
// function reorder(from, to) {
// let newList = JSON.parse(JSON.stringify(value));
// let fromElem = newList[from];
// newList.splice(from, 1);
// newList.splice(to, 0, fromElem);
// value = newList;
// dispatch("reordered", value);
// }
</script> </script>
{#if isTable} {#if isTable}
<tbody class="sortable-container {sortableClass}" bind:this={sortableContainer}> <tbody class="sortable-container {sortableClass}" bind:this={sortableContainer}>
<slot /> <slot/>
</tbody> </tbody>
{:else} {:else}
<div class="sortable-container {sortableClass}" bind:this={sortableContainer}> <div class="sortable-container {sortableClass}" bind:this={sortableContainer}>
<slot /> <slot/>
</div> </div>
{/if} {/if}
+4 -3
View File
@@ -19,9 +19,9 @@
records: [], records: [],
edges: [] edges: []
}; };
export let recordHistory; // export let recordHistory;
export let isCreateMode; export let isCreateMode;
export let isWritable = false; // export let isWritable = false;
export let users; export let users;
let originalContent; let originalContent;
let activeContentTab = ""; let activeContentTab = "";
@@ -154,6 +154,7 @@
<div class="record-edit"> <div class="record-edit">
<div class="tools-header"> <div class="tools-header">
<!-- <Manager managerRecords={recordHistory} {graph}/>--> <!-- <Manager managerRecords={recordHistory} {graph}/>-->
<EditHeader {schema} bind:record {isCreateMode} {graph} bind:activeContentTab/>
{#if isCreateMode} {#if isCreateMode}
<button <button
class="button primary btn-spinner" class="button primary btn-spinner"
@@ -180,7 +181,7 @@
Save Save
</button> </button>
{/if} {/if}
<EditHeader {schema} bind:record {isCreateMode} {graph} bind:activeContentTab/>
</div> </div>
<Title {schema} {record} {isCreateMode}/> <Title {schema} {record} {isCreateMode}/>
@@ -74,7 +74,10 @@
{#if references.length > 0} {#if references.length > 0}
<Sortable sortableClass="mt-3" on:update={reorder}> <Sortable sortableClass="mt-3" on:update={reorder}>
{#each references as reference (reference.id)} {#each references as reference (reference.id)}
<!--This div helps the sorting thing-->
<div>
<PreviewFile record={reference} hasDelete={true} on:remove={removeReference}></PreviewFile> <PreviewFile record={reference} hasDelete={true} on:remove={removeReference}></PreviewFile>
</div>
{/each} {/each}
</Sortable> </Sortable>
{/if} {/if}
@@ -1,11 +1,11 @@
<script> <script>
import {getContext} from "svelte"; import {getContext} from "svelte";
import {insertEdges} from "./reference"; import {insertEdges} from "./reference";
import PreviewCard from "../PreviewCard.svelte";
import {getErrorMessage} from "./errorMessage"; import {getErrorMessage} from "./errorMessage";
import {sortByField} from "../../edges/sortEdges"; import {sortByField} from "../../edges/sortEdges";
import ReferenceInlineButtons from "./ReferenceInlineButtons.svelte"; import ReferenceInlineButtons from "./ReferenceInlineButtons.svelte";
import Sortable from "../../libs/Sortable.svelte"; import Sortable from "../../libs/Sortable.svelte";
import PreviewReference from "../previews/PreviewReference.svelte";
const channel = getContext("channel"); const channel = getContext("channel");
export let record; export let record;
@@ -61,8 +61,8 @@
{#if references.length > 0} {#if references.length > 0}
<Sortable sortableClass="row row-cols-3 mt-3" on:update={reorder}> <Sortable sortableClass="row row-cols-3 mt-3" on:update={reorder}>
{#each references as reference (reference.id)} {#each references as reference (reference.id)}
<div class="col mb-3"> <div>
<PreviewCard <PreviewReference
classes="h-100" classes="h-100"
record={reference} record={reference}
hasDelete={true} hasDelete={true}
@@ -60,7 +60,7 @@
<button <button
type="button" type="button"
class:is-first={!recordId} class:is-first={!recordId}
class=" btn btn-lg btn-link text-decoration-none inline-card-button" class="button"
on:click|preventDefault={(e) => (showOptions = !showOptions)} on:click|preventDefault={(e) => (showOptions = !showOptions)}
> >
<Icon width={24} height={24} icon="circle-plus"/> <Icon width={24} height={24} icon="circle-plus"/>
@@ -95,22 +95,20 @@
</div> </div>
{/if} {/if}
{:else} {:else}
<div class="pb-2 text-start"> <div style="display:flex;align-items: center;gap: 4px">
<div class="mb-2">
<button <button
class="btn btn-sm btn-primary" class="button"
on:click={(e) => createInlineReference(e, schemas[0].name)} on:click={(e) => createInlineReference(e, schemas[0].name)}
>New >New
</button> </button>
<button <button
class="btn btn-sm btn-outline-primary" class="button"
on:click={(e) => openBrowseModal(e, schemas[0].name)} on:click={(e) => openBrowseModal(e, schemas[0].name)}
> >
<Icon icon="magnifying-glass"/> <Icon icon="magnifying-glass"/>
</button </button
> >
</div> </div>
</div>
{/if} {/if}
{#if inLineCreateRecord} {#if inLineCreateRecord}
@@ -21,8 +21,8 @@
</script> </script>
<StatusSelect bind:status={record.status} {record}></StatusSelect>
<div style="display: flex;align-items: center; gap:10px;">
{#if !isCreateMode} {#if !isCreateMode}
<Dropdown orientation="right"> <Dropdown orientation="right">
<div slot="button"> <div slot="button">
@@ -52,3 +52,5 @@
</Dropdown> </Dropdown>
{/if} {/if}
<StatusSelect bind:status={record.status} {record}></StatusSelect>
</div>
+6 -6
View File
@@ -11,7 +11,11 @@
<div class="record-header"> <div class="record-header">
<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)} {previewTitle(channel.schemas, record)}
@@ -19,9 +23,5 @@
New Record New Record
{/if} {/if}
</span> </span>
<a
class="schema-name"
href="{channel.lucentUrl}/content/{schema.name}"
>{schema.label.toUpperCase()}</a
>
</div> </div>
@@ -0,0 +1,56 @@
<script>
import Icon from "../../common/Icon.svelte";
import { getContext, createEventDispatcher } from "svelte";
import { previewTitle } from "./../Preview";
import Status from "./../Status.svelte";
const dispatch = createEventDispatcher();
const channel = getContext("channel");
export let graph;
export let record;
export let hasDelete = false;
let schema = channel.schemas.find((aschema) => aschema.name === record.schema);
let cardTitle = previewTitle(channel.schemas, record, graph);
function remove(e) {
e.preventDefault();
dispatch("remove", record.id);
}
</script>
<div class="preview-reference">
<div style="display: flex;align-items: center;gap: 10px;">
<div class="title">
<div>
<a
class="record-title"
href="{channel.lucentUrl}/records/{record.id}"
>
{cardTitle}
</a>
<small class="d-block">
from {schema.label}
{#if record.status === "draft"}
<Status status={record.status}/>
{/if}
</small>
</div>
</div>
</div>
{#if hasDelete}
<div class="trash-action">
<button
class="button"
on:click={remove}
>
<Icon icon="trash-can"/>
</button>
</div>
{/if}
</div>
+7
View File
@@ -45,3 +45,10 @@
font-weight: normal; font-weight: normal;
} }
} }
.button-text{
border: none;
padding: 0;
background: transparent;
cursor: pointer;
}
+9 -3
View File
@@ -14,18 +14,19 @@ body:has(dialog[open]) {
} }
dialog { dialog {
margin: 10px auto; margin: 2vh auto;
background-color: #fff; background-color: #fff;
padding: 34px; padding: 34px;
border: none; border: none;
border-radius: 5px; border-radius: 5px;
overflow: auto; overflow: auto;
max-height: 96vh;
//position: relative; //position: relative;
.close { .close {
position: absolute; position: absolute;
top: 20px; top: 10px;
right: 20px; right: 0px;
} }
.dialog-body { .dialog-body {
@@ -44,4 +45,9 @@ dialog::backdrop {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
position: sticky;
top: -34px;
z-index: 999;
background: #fff;
padding: 10px 0;
} }
+8 -2
View File
@@ -1,4 +1,4 @@
.preview-file{ .preview-file,.preview-reference{
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -24,7 +24,13 @@
} }
} }
} }
.preview-reference{
filter: brightness(97%);
padding: 10px 20px;
margin-bottom: 4px;
}
.sortable-ghost{ .sortable-ghost{
border: 2px dashed var(--primary); border: 2px dashed var(--primary);
} }
.sortable-drag { opacity: 0 !important; } .sortable-ghost { opacity: 1 !important; }
+9 -1
View File
@@ -1,5 +1,12 @@
.record-edit { .record-edit {
position: relative;
.invalid-feedback{
color: var(--error);
font-size: 15px;
line-height: 20px;
margin-top: 10px;
}
} }
.record-header { .record-header {
@@ -19,6 +26,7 @@
margin: 30px 0 0; margin: 30px 0 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
gap: 10px; gap: 10px;
font-size: 14px; font-size: 14px;
position: relative; position: relative;
@@ -26,7 +34,7 @@
padding: 10px; padding: 10px;
border-radius: 12px; border-radius: 12px;
background: var(--background); background: var(--background);
filter: brightness(90%); filter: brightness(97%);
} }
.editor-field { .editor-field {
+2 -1
View File
@@ -34,7 +34,8 @@
padding: 3px 12px 6px; padding: 3px 12px 6px;
color: var(--text); color: var(--text);
filter: brightness(94%); filter: brightness(94%);
border-bottom: 0px solid var(--border-color); border: none;
//border-bottom: 0px solid var(--border-color);
border-radius: 12px; border-radius: 12px;
&:hover { &:hover {
+22
View File
@@ -19,3 +19,25 @@
.toolbar-filters{ display: flex; .toolbar-filters{ display: flex;
align-items: center; align-items: center;
gap: 5px;} gap: 5px;}
.applied-filters{
display: flex;
gap: 4px;
margin-top: 10px;
.applied-filter {
font-size: 13px;
border-radius: 12px;
background: var(--background);
padding: 3px 10px;
display: flex;
justify-content: center;
gap: 4px;
line-height: 22px;
}
.applied-filter:hover {
opacity: .8;
background-color: #eee;
}
}
+1
View File
@@ -126,6 +126,7 @@ $themes: (
--secondary: #7bc8f1; --secondary: #7bc8f1;
--accent: #5086ed; --accent: #5086ed;
--success: #80c671; --success: #80c671;
--error: red;
} }