added support for linking to the record preview/update form and some other minor improvements
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
import tooltip from "@/actions/tooltip";
|
||||
import { setErrors } from "@/stores/errors";
|
||||
import { confirm } from "@/stores/confirmation";
|
||||
import { addSuccessToast } from "@/stores/toasts";
|
||||
import { addSuccessToast, addErrorToast } from "@/stores/toasts";
|
||||
import Field from "@/components/base/Field.svelte";
|
||||
import Toggler from "@/components/base/Toggler.svelte";
|
||||
import ModelDateIcon from "@/components/base/ModelDateIcon.svelte";
|
||||
@@ -38,14 +38,14 @@
|
||||
let record = null;
|
||||
let initialDraft = null;
|
||||
let isSaving = false;
|
||||
let confirmClose = false; // prevent close recursion
|
||||
let confirmHide = false; // prevent close recursion
|
||||
let uploadedFilesMap = {}; // eg.: {"field1":[File1, File2], ...}
|
||||
let deletedFileNamesMap = {}; // eg.: {"field1":[0, 1], ...}
|
||||
let originalSerializedData = JSON.stringify(null);
|
||||
let originalSerializedData = JSON.stringify(original);
|
||||
let serializedData = originalSerializedData;
|
||||
let activeTab = tabFormKey;
|
||||
let isNew = true;
|
||||
let isLoaded = false;
|
||||
let isLoading = true;
|
||||
|
||||
$: isAuthCollection = collection?.type === "auth";
|
||||
|
||||
@@ -60,16 +60,16 @@
|
||||
|
||||
$: isNew = !original || !original.id;
|
||||
|
||||
$: canSave = isNew || hasChanges;
|
||||
$: canSave = !isLoading && (isNew || hasChanges);
|
||||
|
||||
$: if (isLoaded) {
|
||||
$: if (!isLoading) {
|
||||
updateDraft(serializedData);
|
||||
}
|
||||
|
||||
export function show(model) {
|
||||
load(model);
|
||||
|
||||
confirmClose = true;
|
||||
confirmHide = true;
|
||||
|
||||
activeTab = tabFormKey;
|
||||
|
||||
@@ -80,14 +80,49 @@
|
||||
return recordPanel?.hide();
|
||||
}
|
||||
|
||||
function forceHide() {
|
||||
confirmHide = false;
|
||||
hide();
|
||||
}
|
||||
|
||||
async function resolveModel(model) {
|
||||
if (model && typeof model === "string") {
|
||||
// load from id
|
||||
try {
|
||||
return await ApiClient.collection(collection.id).getOne(model);
|
||||
} catch (err) {
|
||||
if (!err.isAbort) {
|
||||
forceHide();
|
||||
console.warn("resolveModel:", err);
|
||||
addErrorToast(`Unable to load record with id "${model}"`);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
async function load(model) {
|
||||
isLoaded = false;
|
||||
setErrors({}); // reset errors
|
||||
original = model || {};
|
||||
record = structuredClone(original);
|
||||
isLoading = true;
|
||||
|
||||
// resets
|
||||
setErrors({});
|
||||
uploadedFilesMap = {};
|
||||
deletedFileNamesMap = {};
|
||||
|
||||
// load the minimum model data if possible to minimize layout shifts
|
||||
original =
|
||||
typeof model === "string"
|
||||
? { id: model, collectionId: collection?.id, collectionName: collection?.name }
|
||||
: model || {};
|
||||
record = structuredClone(original);
|
||||
|
||||
// resolve the complete model
|
||||
original = (await resolveModel(model)) || {};
|
||||
record = structuredClone(original);
|
||||
|
||||
// wait to populate the fields to get the normalized values
|
||||
await tick();
|
||||
|
||||
@@ -100,7 +135,8 @@
|
||||
}
|
||||
|
||||
originalSerializedData = JSON.stringify(record);
|
||||
isLoaded = true;
|
||||
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
async function replaceOriginal(newOriginal) {
|
||||
@@ -204,8 +240,7 @@
|
||||
deleteDraft();
|
||||
|
||||
if (hidePanel) {
|
||||
confirmClose = false;
|
||||
hide();
|
||||
forceHide();
|
||||
} else {
|
||||
replaceOriginal(result);
|
||||
}
|
||||
@@ -406,11 +441,13 @@
|
||||
{hasEditorField ? 'overlay-panel-xl' : 'overlay-panel-lg'}
|
||||
{isAuthCollection && !isNew ? 'colored-header' : ''}
|
||||
"
|
||||
btnClose={!isLoading}
|
||||
escClose={!isLoading}
|
||||
overlayClose={!isLoading}
|
||||
beforeHide={() => {
|
||||
if (hasChanges && confirmClose) {
|
||||
if (hasChanges && confirmHide) {
|
||||
confirm("You have unsaved changes. Do you really want to close the panel?", () => {
|
||||
confirmClose = false;
|
||||
hide();
|
||||
forceHide();
|
||||
});
|
||||
|
||||
return false;
|
||||
@@ -425,10 +462,15 @@
|
||||
on:show
|
||||
>
|
||||
<svelte:fragment slot="header">
|
||||
<h4 class="panel-title">
|
||||
{isNew ? "New" : "Edit"}
|
||||
<strong>{collection?.name}</strong> record
|
||||
</h4>
|
||||
{#if isLoading}
|
||||
<span class="loader loader-sm" />
|
||||
<h4 class="panel-title txt-hint">Loading...</h4>
|
||||
{:else}
|
||||
<h4 class="panel-title">
|
||||
{isNew ? "New" : "Edit"}
|
||||
<strong>{collection?.name}</strong> record
|
||||
</h4>
|
||||
{/if}
|
||||
|
||||
{#if !isNew}
|
||||
<div class="flex-fill" />
|
||||
@@ -502,7 +544,7 @@
|
||||
on:submit|preventDefault={save}
|
||||
on:keydown={handleFormKeydown}
|
||||
>
|
||||
{#if !hasChanges && initialDraft}
|
||||
{#if !hasChanges && initialDraft && !isLoading}
|
||||
<div class="block" out:slide={{ duration: 150 }}>
|
||||
<div class="alert alert-info m-0">
|
||||
<div class="icon">
|
||||
@@ -546,7 +588,7 @@
|
||||
<input
|
||||
type="text"
|
||||
id={uniqueId}
|
||||
placeholder="Leave empty to auto generate..."
|
||||
placeholder={!isLoading ? "Leave empty to auto generate..." : ""}
|
||||
minlength="15"
|
||||
readonly={!isNew}
|
||||
bind:value={record.id}
|
||||
@@ -602,7 +644,12 @@
|
||||
</div>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<button type="button" class="btn btn-transparent" disabled={isSaving} on:click={() => hide()}>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-transparent"
|
||||
disabled={isSaving || isLoading}
|
||||
on:click={() => hide()}
|
||||
>
|
||||
<span class="txt">Cancel</span>
|
||||
</button>
|
||||
|
||||
@@ -610,7 +657,7 @@
|
||||
type="submit"
|
||||
form={formId}
|
||||
class="btn btn-expanded"
|
||||
class:btn-loading={isSaving}
|
||||
class:btn-loading={isSaving || isLoading}
|
||||
disabled={!canSave || isSaving}
|
||||
>
|
||||
<span class="txt">{isNew ? "Create" : "Save changes"}</span>
|
||||
|
||||
Reference in New Issue
Block a user