fix(components): make it so that reordering chapters in the story form no longer causes catastrophic state loss, rendering the tinymce components useless
all hail PORTALS!!!!!
This commit is contained in:
parent
ec050390ad
commit
739cfb5eff
@ -19,6 +19,12 @@
|
|||||||
<tinymce-editor
|
<tinymce-editor
|
||||||
v-bind="field"
|
v-bind="field"
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@change="
|
||||||
|
(e) => {
|
||||||
|
console.debug(e);
|
||||||
|
setValue(e);
|
||||||
|
}
|
||||||
|
"
|
||||||
:initial-value="value"
|
:initial-value="value"
|
||||||
v-model:model-value="field.value"
|
v-model:model-value="field.value"
|
||||||
tinymce-script-src="/tinymce/tinymce.min.js"
|
tinymce-script-src="/tinymce/tinymce.min.js"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import draggable from "vuedraggable";
|
import draggable from "vuedraggable";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
import lmove from "lodash-move";
|
import lmove from "lodash-move";
|
||||||
import { Field, FieldArray, useForm } from "vee-validate";
|
import { Field, FieldArray, useForm, useFieldArray } from "vee-validate";
|
||||||
import { storySchema } from "@client/storyFormSchema";
|
import { storySchema } from "@client/storyFormSchema";
|
||||||
import { FormStory, defaultChapter } from "@client/types/form/story";
|
import { FormStory, defaultChapter } from "@client/types/form/story";
|
||||||
import { autoEdit, autoSave, debouncedAutoEdit, debouncedAutoSave } from "@client/utils";
|
import { autoEdit, autoSave, debouncedAutoEdit, debouncedAutoSave } from "@client/utils";
|
||||||
@ -18,9 +18,13 @@
|
|||||||
endpointMethod: "put" | "post";
|
endpointMethod: "put" | "post";
|
||||||
submitText?: string;
|
submitText?: string;
|
||||||
}>();
|
}>();
|
||||||
|
let w;
|
||||||
|
onMounted(() => {
|
||||||
|
w = window;
|
||||||
|
});
|
||||||
const dc = defaultChapter;
|
const dc = defaultChapter;
|
||||||
// data: FormStory;
|
// data: FormStory;
|
||||||
const data = defineModel<FormStory>("data", {
|
const sdata = defineModel<FormStory>("data", {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
let drag = false;
|
let drag = false;
|
||||||
@ -54,114 +58,121 @@
|
|||||||
const { values, setFieldValue, handleSubmit } = useForm<FormStory>({
|
const { values, setFieldValue, handleSubmit } = useForm<FormStory>({
|
||||||
keepValuesOnUnmount: true,
|
keepValuesOnUnmount: true,
|
||||||
validationSchema: storySchema,
|
validationSchema: storySchema,
|
||||||
initialValues: data.value,
|
initialValues: sdata.value,
|
||||||
});
|
});
|
||||||
|
// const { push, remove, move, fields } = useFieldArray<FormChapter>("chapters");
|
||||||
const subCb = handleSubmit(onSubmit);
|
const subCb = handleSubmit(onSubmit);
|
||||||
|
|
||||||
|
const pushHOF = (push) => (e) => {
|
||||||
|
if (!Array.isArray(values.chapters)) {
|
||||||
|
// noinspection TypeScriptValidateTypes
|
||||||
|
setFieldValue("chapters", []);
|
||||||
|
}
|
||||||
|
const chaps = [...toRaw(values.chapters)];
|
||||||
|
let lastIndex = chaps.length - 1;
|
||||||
|
if (lastIndex < 0) lastIndex = 0;
|
||||||
|
let lastChapter = chaps[lastIndex];
|
||||||
|
// log.debug('chaptrs->', chaps);
|
||||||
|
// log.debug('lastIndex->', lastIndex, lastChapter);
|
||||||
|
let newChapter = Object.assign({}, defaultChapter, {
|
||||||
|
summary: lastChapter?.summary || "",
|
||||||
|
index: (lastChapter?.index || 0) + 1,
|
||||||
|
bands: lastChapter?.bands || [],
|
||||||
|
characters: lastChapter?.characters || [],
|
||||||
|
relationships: lastChapter?.relationships || [],
|
||||||
|
uuidKey: v4(),
|
||||||
|
genre: lastChapter?.genre || [],
|
||||||
|
});
|
||||||
|
// console.debug("nc->", newChapter);
|
||||||
|
// console.debug("pushi -> ", push);
|
||||||
|
push(newChapter);
|
||||||
|
sdata.value.chapters.push(newChapter);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<!-- <vee-form
|
<form data-testid="storyform" @submit="subCb" @change="() => (canDraft ? debouncedAutoSave(values) : debouncedAutoEdit(values, endpoint, endpointMethod))">
|
||||||
:keep-values="true"
|
|
||||||
v-slot="{ values, setFieldValue }"
|
|
||||||
:validation-schema="storySchema"
|
|
||||||
:initial-values="data"
|
|
||||||
@submit="onSubmit"
|
|
||||||
@invalid-submit="inval"
|
|
||||||
> -->
|
|
||||||
<form @submit="subCb" @change="() => (canDraft ? 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 }">
|
||||||
<a-form-item label="Title" :help="errorMessage" :validate-status="!!errorMessage ? 'error' : ''">
|
<a-form-item label="Title" :help="errorMessage" :validate-status="!!errorMessage ? 'error' : ''">
|
||||||
<a-input v-bind="field" :value="value" />
|
<a-input :data-testid="`storyform.${field.name}`" v-bind="field" :value="value" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</Field>
|
</Field>
|
||||||
<a-form-item label="Co-author (optional)">
|
<a-form-item label="Co-author (optional)">
|
||||||
<find-user :initial-option="data.coAuthor" fieldName="coAuthor" :multi="false" />
|
<find-user data-testid="storyform.coauthor" :initial-option="sdata.coAuthor" fieldName="coAuthor" :multi="false" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<Field :unchecked-value="false" :value="true" type="checkbox" name="completed" v-slot="{ value, field, errorMessage }">
|
<Field :unchecked-value="false" :value="true" type="checkbox" name="completed" v-slot="{ value, field, errorMessage }">
|
||||||
<a-checkbox v-bind="field"> Complete </a-checkbox>
|
<a-checkbox :data-testid="`storyform.${field.name}`" v-bind="field"> Complete </a-checkbox>
|
||||||
</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 }">
|
||||||
|
<div>
|
||||||
|
<div v-for="(element, index) in values.chapters">
|
||||||
|
<client-only>
|
||||||
|
<Teleport :to="`#chapter-\\[${element.uuidKey}\\]`">
|
||||||
|
<a-collapse v-model:active-key="expandos" collapsible="icon">
|
||||||
|
<template #expandIcon="{ isActive }">
|
||||||
|
<span :data-testid="`storyform.chapters[${index}].collapse`"> <RightOutlined :rotate="isActive ? 90 : undefined" /></span>
|
||||||
|
</template>
|
||||||
|
<a-collapse-panel :key="`${element.uuidKey}`">
|
||||||
|
<template #header>
|
||||||
|
<div :data-testid="`storyform.chapters[${index}].header`" style="display: flex; justify-content: space-between">
|
||||||
|
<span :data-testid="`storyform.chapters[${index}].titleEl`">{{ values.chapters[index]?.chapterTitle || "Untitled" }}</span>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
(e) => {
|
||||||
|
// let localFields = toRaw(fields);
|
||||||
|
// log.debug(`${index} | ${element.index}`);
|
||||||
|
// log.debug('fields->', localFields);
|
||||||
|
data.chapters.splice(index, 1);
|
||||||
|
remove(index);
|
||||||
|
// todo renumber
|
||||||
|
// renumber()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<icon istyle="regular" name="trash" />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<single-chapter :data="element" :name="`chapters[${index}]`" />
|
||||||
|
</a-collapse-panel>
|
||||||
|
</a-collapse>
|
||||||
|
</Teleport>
|
||||||
|
</client-only>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<draggable
|
<draggable
|
||||||
:component-data="{ type: 'transtion-group' }"
|
:component-data="{ type: 'transtion-group', 'data-testid': 'storyform.chapters' }"
|
||||||
@start="drag = true"
|
@start="drag = true"
|
||||||
@end="drag = false"
|
@end="drag = false"
|
||||||
v-model="values.chapters"
|
v-model="values.chapters"
|
||||||
tag="div"
|
tag="div"
|
||||||
|
data-testid="storyform.chapters"
|
||||||
item-key="uuidKey"
|
item-key="uuidKey"
|
||||||
@change="
|
@change="
|
||||||
(e) => {
|
(e) => {
|
||||||
|
console.log(e);
|
||||||
if (e.moved) {
|
if (e.moved) {
|
||||||
// log.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);
|
||||||
|
// w.tinymce.remove();
|
||||||
// log.debug(toRaw(acData.chapters.map((a) => toRaw(a))));
|
// log.debug(toRaw(acData.chapters.map((a) => toRaw(a))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<a-collapse v-model:active-key="expandos" collapsible="icon">
|
<div :id="`chapter-[${element.uuidKey}]`"></div>
|
||||||
<a-collapse-panel :key="`${element.uuidKey}`">
|
|
||||||
<template #header>
|
|
||||||
{{ values.chapters[index]?.chapterTitle || "Untitled" }}
|
|
||||||
<a-button
|
|
||||||
@click="
|
|
||||||
(e) => {
|
|
||||||
let localFields = toRaw(fields);
|
|
||||||
// log.debug(`${index} | ${element.index}`);
|
|
||||||
// log.debug('fields->', localFields);
|
|
||||||
data.chapters.splice(index, 1);
|
|
||||||
remove(index);
|
|
||||||
// todo renumber
|
|
||||||
// renumber()
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<icon istyle="regular" name="trash" />
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
<single-chapter :data="element" :name="`chapters[${index}]`" />
|
|
||||||
</a-collapse-panel>
|
|
||||||
</a-collapse>
|
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-button
|
<a-button data-testid="storyform.addChapter" :onClick="pushHOF(push)"> Add chapter </a-button>
|
||||||
@click="
|
|
||||||
(e) => {
|
|
||||||
if (!Array.isArray(values.chapters)) {
|
|
||||||
// noinspection TypeScriptValidateTypes
|
|
||||||
setFieldValue('chapters', []);
|
|
||||||
}
|
|
||||||
const chaps = [...toRaw(values.chapters)];
|
|
||||||
let lastIndex = chaps.length - 1;
|
|
||||||
if (lastIndex < 0) lastIndex = 0;
|
|
||||||
let lastChapter = chaps[lastIndex];
|
|
||||||
// log.debug('chaptrs->', chaps);
|
|
||||||
// log.debug('lastIndex->', lastIndex, lastChapter);
|
|
||||||
let newChapter = Object.assign({}, defaultChapter, {
|
|
||||||
summary: lastChapter?.summary || '',
|
|
||||||
index: (lastChapter?.index || 0) + 1,
|
|
||||||
bands: lastChapter?.bands || [],
|
|
||||||
characters: lastChapter?.characters || [],
|
|
||||||
relationships: lastChapter?.relationships || [],
|
|
||||||
uuidKey: v4(),
|
|
||||||
genre: lastChapter?.genre || [],
|
|
||||||
});
|
|
||||||
// log.debug('nc->', newChapter);
|
|
||||||
push(newChapter);
|
|
||||||
data.chapters.push(newChapter);
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
Add chapter
|
|
||||||
</a-button>
|
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
</field-array>
|
</field-array>
|
||||||
<a-button type="primary" html-type="submit">{{ submitText || "Post" }}</a-button>
|
<a-button type="primary" html-type="submit">{{ submitText || "Post" }}</a-button>
|
||||||
<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>
|
||||||
<!-- </vee-form> -->
|
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user