229 lines
6.8 KiB
Svelte
229 lines
6.8 KiB
Svelte
<script>
|
|
import {afterUpdate, createEventDispatcher, onMount,getContext} from "svelte";
|
|
|
|
import {isEqual} from "lodash";
|
|
import FormField from "./FormField.svelte";
|
|
import FilePreview from "./FilePreview.svelte";
|
|
import ContentTabs from "./ContentTabs.svelte";
|
|
import StatusSelect from "./form/StatusSelect.svelte";
|
|
import ErrorAlert from "../common/ErrorAlert.svelte";
|
|
|
|
const channel = getContext("channel");
|
|
const dispatch = createEventDispatcher();
|
|
export let schema;
|
|
export let record;
|
|
export let graph = {
|
|
records: [],
|
|
edges: []
|
|
};
|
|
export let isCreateMode;
|
|
let originalContent;
|
|
let activeContentTab = "";
|
|
let hasUnsavedData = false;
|
|
$: validationErrors = null;
|
|
$: errorMessage = validationErrors
|
|
? `Record submission failed. ${
|
|
Object.entries(validationErrors).length
|
|
} error(s)`
|
|
: null;
|
|
|
|
let activeFields = schema.fields.filter(
|
|
(f) => f.name !== "id"
|
|
);
|
|
|
|
let tabname = "_default";
|
|
let fieldToTabs = schema.fields.reduce((c, f) => {
|
|
if (f.ui === "tab") {
|
|
tabname = f.name;
|
|
return c;
|
|
}
|
|
|
|
c[tabname] = [...(c[tabname] ?? []), f.name];
|
|
return c;
|
|
}, []);
|
|
|
|
onMount(() => {
|
|
setOriginalContent();
|
|
});
|
|
|
|
function setOriginalContent() {
|
|
originalContent = {
|
|
data: JSON.parse(JSON.stringify(record.data)),
|
|
schema: record.schema,
|
|
status: record.status,
|
|
_sys: JSON.parse(JSON.stringify(record._sys)),
|
|
_file: JSON.parse(JSON.stringify(record._file)),
|
|
edges: JSON.parse(JSON.stringify(graph.edges)),
|
|
};
|
|
}
|
|
|
|
afterUpdate(() => {
|
|
hasUnsavedData = checkUnsavedData();
|
|
});
|
|
|
|
function beforeUnload(e) {
|
|
// Cancel the event as stated by the standard.
|
|
// e.preventDefault();
|
|
// console.log(hasUnsavedData);
|
|
if (hasUnsavedData) {
|
|
return (e.returnValue =
|
|
"You have unsaved changes. Are you sure you want to exit?");
|
|
}
|
|
// Chrome requires returnValue to be set.
|
|
// e.returnValue = "";
|
|
delete e["returnValue"];
|
|
// more compatibility
|
|
// return true;
|
|
return "...";
|
|
}
|
|
|
|
function checkUnsavedData() {
|
|
if (isCreateMode) {
|
|
return false;
|
|
}
|
|
return !isEqual(originalContent, {
|
|
data: record.data,
|
|
schema: record.schema,
|
|
status: record.status,
|
|
_sys: record._sys,
|
|
_file: record._file,
|
|
edges: graph.edges,
|
|
});
|
|
}
|
|
|
|
function cancel(e) {
|
|
e.preventDefault();
|
|
dispatch("cancel");
|
|
}
|
|
|
|
function save(e) {
|
|
e.preventDefault();
|
|
|
|
console.log("SAVE: Attempt");
|
|
validationErrors = null;
|
|
errorMessage = "";
|
|
return new Promise(function (resolve, reject) {
|
|
if (!hasUnsavedData && !isCreateMode) {
|
|
resolve(null);
|
|
return;
|
|
}
|
|
if (!record) {
|
|
resolve(null);
|
|
return;
|
|
}
|
|
// remove trashed edges
|
|
graph.edges = graph.edges?.filter((edge) => !edge._isTrashed && edge.source === record.id) ?? [];
|
|
|
|
|
|
axios
|
|
.post(channel.lucentUrl + "/records", {
|
|
record: record,
|
|
edges: graph.edges,
|
|
isCreateMode: isCreateMode,
|
|
})
|
|
.then(function (response) {
|
|
console.log("SAVE: SAVED INLINE");
|
|
|
|
record = response.data.records[0];
|
|
graph = response.data;
|
|
if (!isCreateMode) {
|
|
setOriginalContent();
|
|
}
|
|
dispatch("inlinesaved", {
|
|
records: [record],
|
|
});
|
|
resolve(null);
|
|
})
|
|
.catch(function (error) {
|
|
// setOriginalContent();
|
|
if (error.response) {
|
|
if (typeof error.response.data.error === "string") {
|
|
errorMessage = error.response.data.error;
|
|
} else {
|
|
validationErrors = error.response.data.error;
|
|
}
|
|
}
|
|
resolve(null);
|
|
// msgSuccess = null;
|
|
// msgError = error.response.data.error;
|
|
// submitted = false;
|
|
});
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<svelte:window on:beforeunload={beforeUnload}/>
|
|
|
|
<div class="inline-edit my-4">
|
|
<ErrorAlert message={errorMessage}/>
|
|
|
|
<div class=" mt-1">
|
|
<ContentTabs
|
|
{schema}
|
|
{isCreateMode}
|
|
bind:active={activeContentTab}
|
|
{record}
|
|
/>
|
|
<FilePreview {record} {schema}/>
|
|
<!-- <fieldset disabled="disabled"> -->
|
|
{#each activeFields as field (field.name)}
|
|
{#if activeContentTab === field.group}
|
|
<FormField
|
|
bind:data={record.data}
|
|
bind:graph={graph}
|
|
{field}
|
|
{schema}
|
|
{record}
|
|
{validationErrors}
|
|
{isCreateMode}
|
|
/>
|
|
{/if}
|
|
{/each}
|
|
<!-- </fieldset> -->
|
|
</div>
|
|
<div>
|
|
<div class="d-flex mt-3 align-items-center justify-content-center">
|
|
{#if schema.hasDrafts}
|
|
<StatusSelect bind:status={record.status} {schema}/>
|
|
{/if}
|
|
{#if isCreateMode}
|
|
<button
|
|
class="ms-2 btn btn-primary btn-spinner"
|
|
on:click={save}
|
|
>
|
|
<span
|
|
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}
|
|
>
|
|
<span
|
|
class="spinner-border spinner-border-sm"
|
|
role="status"
|
|
aria-hidden="true"
|
|
/>
|
|
Save
|
|
</button>
|
|
{/if}
|
|
<button class="ms-2 btn btn-link" on:click={cancel}>
|
|
cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.inline-edit {
|
|
padding: 44px;
|
|
background-color: #eee;
|
|
border-radius: 32px;
|
|
}
|
|
</style>
|