refactor(components): update story form

add `draftData` prop to distinguish whether we're editing a draft or a published story
actually renumber chapter indexes after reordering
use draftData prop in form change callback
This commit is contained in:
parent 4838b7b624
commit 6016813f4c
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C

@ -5,7 +5,7 @@
import { Field, FieldArray, useForm, useFieldArray } from "vee-validate"; import { Field, FieldArray, useForm, useFieldArray } from "vee-validate";
import { ASpin } from "#components"; import { ASpin } from "#components";
import { storySchema } from "@client/storyFormSchema"; import { storySchema } from "@client/storyFormSchema";
import { FormStory, defaultChapter } from "@client/types/form/story"; import { FormStory, defaultChapter, FormChapter } from "@client/types/form/story";
import { autoEdit, autoSave, debouncedAutoEdit, debouncedAutoSave } from "@client/utils"; import { autoEdit, autoSave, debouncedAutoEdit, debouncedAutoSave } from "@client/utils";
import findUser from "~/components/findUser.vue"; import findUser from "~/components/findUser.vue";
@ -20,17 +20,16 @@
endpoint: string; endpoint: string;
endpointMethod: "put" | "post"; endpointMethod: "put" | "post";
submitText?: string; submitText?: string;
draftData?: {
endpoint: string;
endpointMethod: "put" | "post";
};
}>(); }>();
let w;
onMounted(() => {
w = window;
});
const dc = defaultChapter; const dc = defaultChapter;
// data: FormStory;
const sdata = defineModel<FormStory>("data", { const sdata = defineModel<FormStory>("data", {
required: true, required: true,
}); });
let drag = false; let drag: boolean = false;
const expandos = ref<string[]>([]); const expandos = ref<string[]>([]);
function logSubmit(values, actions) { function logSubmit(values, actions) {
@ -46,27 +45,32 @@
otherBtnInvoked.value = false; otherBtnInvoked.value = false;
await autoSave(values); await autoSave(values);
} else { } else {
const { data: dat } = await useApiFetch(`/story/new`, { const { data: dat } = await useApiFetch<any>(`/story/new`, {
method: "post", method: "post",
body: values, body: values,
}); });
if (dat.success) { if (dat.value.success) {
await router.push(`/story/${dat.story._id}/1`); await router.push(`/story/${dat.value.story._id}/1`);
} }
} }
} else { } else {
await autoEdit(values, props.endpoint, props.endpointMethod); await autoEdit(values, props.endpoint, props.endpointMethod);
} }
} }
function inval({ values, errors, results }) {
logSubmit(values, undefined);
}
const { values, setFieldValue, handleSubmit } = useForm<FormStory>({ const { values, setFieldValue, handleSubmit } = useForm<FormStory>({
keepValuesOnUnmount: true, keepValuesOnUnmount: true,
validationSchema: storySchema, validationSchema: storySchema,
initialValues: sdata.value, initialValues: sdata.value,
}); });
// const { push, remove, move, fields } = useFieldArray<FormChapter>("chapters"); function renumber(update: (idx: number, value: FormChapter) => void) {
for (let i = 0; i < values.chapters.length; i++) {
const nv = values.chapters[i];
nv.index = i + 1;
update(i, nv);
sdata.value.chapters[i].index = i + 1;
}
}
const subCb = handleSubmit(onSubmit); const subCb = handleSubmit(onSubmit);
const pushHOF = (push) => (e) => { const pushHOF = (push) => (e) => {
@ -96,7 +100,18 @@
}; };
</script> </script>
<template> <template>
<form data-testid="storyform" @submit="subCb" @change="() => (canDraft ? debouncedAutoSave(values) : debouncedAutoEdit(values, endpoint, endpointMethod))"> <form
data-testid="storyform"
@submit="subCb"
@change="
() =>
canDraft
? draftData
? debouncedAutoSave(values, draftData.endpoint, draftData.endpointMethod)
: debouncedAutoSave(values)
: debouncedAutoEdit(values, endpoint, endpointMethod)
"
>
<!-- <a-form v-bind:model="acData"> --> <!-- <a-form v-bind:model="acData"> -->
<Field name="title" v-slot="{ value, field, errorMessage }"> <Field name="title" v-slot="{ value, field, errorMessage }">
@ -112,30 +127,26 @@
</Field> </Field>
<a-divider /> <a-divider />
<!-- <test1/> --> <!-- <test1/> -->
<field-array name="chapters" v-slot="{ fields, push, remove, move }"> <field-array name="chapters" v-slot="{ fields, push, remove, move, update }">
<client-only :fallback="h(ASpin)"> <client-only :fallback="h(ASpin)">
<div> <div>
<div v-for="(element, index) in data.chapters"> <div v-for="(element, index) in values.chapters">
<client-only> <client-only>
<Teleport :to="`#chapter-\\[${element.uuidKey}\\]`"> <Teleport :to="`#chapter-\\[${element.uuidKey}\\]`">
<a-collapse v-model:active-key="expandos" collapsible="icon"> <a-collapse v-model:active-key="expandos" collapsible="icon">
<template #expandIcon="{ isActive }"> <template #expandIcon="{ isActive }">
<span :data-testid="`storyform.chapters[${index}].collapse`"> <RightOutlined :rotate="isActive ? 90 : undefined" /></span> <span :data-testid="`storyform.chapters[${index}].collapse`"> <RightOutlined :rotate="isActive ? 90 : undefined" /></span>
</template> </template>
<a-collapse-panel :key="`${element.uuidKey}`"> <a-collapse-panel :key="`${element.uuidKey}`" :data-testid="`storyform.chapters[${index}].outer`">
<template #header> <template #header>
<div :data-testid="`storyform.chapters[${index}].header`" style="display: flex; justify-content: space-between"> <div :data-testid="`storyform.chapters[${index}].header`" style="display: flex; align-items: center; justify-content: space-between">
<span :data-testid="`storyform.chapters[${index}].titleEl`">{{ values.chapters[index]?.chapterTitle || "Untitled" }}</span> <span :data-testid="`storyform.chapters[${index}].titleEl`">{{ values.chapters[index]?.chapterTitle || "Untitled" }}</span>
<a-button <a-button
@click=" @click="
(e) => { (e) => {
// let localFields = toRaw(fields);
// log.debug(`${index} | ${element.index}`);
// log.debug('fields->', localFields);
data.chapters.splice(index, 1); data.chapters.splice(index, 1);
remove(index); remove(index);
// todo renumber renumber(update);
// renumber()
} }
" "
> >
@ -172,6 +183,7 @@
console.debug(e.moved); console.debug(e.moved);
move(e.moved.oldIndex, e.moved.newIndex); move(e.moved.oldIndex, e.moved.newIndex);
data.chapters = lmove(data.chapters, e.moved.oldIndex, e.moved.newIndex); data.chapters = lmove(data.chapters, e.moved.oldIndex, e.moved.newIndex);
renumber(update);
// w.tinymce.remove(); // w.tinymce.remove();
// log.debug(toRaw(acData.chapters.map((a) => toRaw(a)))); // log.debug(toRaw(acData.chapters.map((a) => toRaw(a))));
} }
@ -191,3 +203,11 @@
<a-button html-type="submit" v-if="canDraft" @click="() => (otherBtnInvoked = true)"> Save for Later </a-button> <a-button html-type="submit" v-if="canDraft" @click="() => (otherBtnInvoked = true)"> Save for Later </a-button>
</form> </form>
</template> </template>
<style>
.ant-collapse-item > .ant-collapse-header {
align-items: center !important;
}
.ant-collapse-header.ant-collapse-icon-collapsible-only {
align-items: center !important;
}
</style>