Refactor editor as hook / fix infinite submit bug
Move state of editor back up to parent We have to do this later anyways to allow parent to edit
This commit is contained in:
parent
5fa2925ba8
commit
3f30becb93
|
@ -4,33 +4,20 @@ import { useEditor, EditorContent, JSONContent, Content } from '@tiptap/react'
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useWarnUnsavedChanges } from 'web/hooks/use-warn-unsaved-changes'
|
|
||||||
import { Linkify } from './linkify'
|
import { Linkify } from './linkify'
|
||||||
|
|
||||||
const LINE_HEIGHT = 2
|
const LINE_HEIGHT = 2
|
||||||
|
|
||||||
const proseClass = 'prose prose-sm prose-p:my-0 prose-li:my-0 max-w-none'
|
const proseClass = 'prose prose-sm prose-p:my-0 prose-li:my-0 max-w-none'
|
||||||
|
|
||||||
export function TextEditor(props: {
|
export function useTextEditor(props: {
|
||||||
className?: string
|
|
||||||
rows?: number
|
rows?: number
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
max?: number
|
max?: number
|
||||||
defaultValue?: Content
|
defaultValue?: Content
|
||||||
onSend: (data: JSONContent) => void
|
|
||||||
sending: boolean
|
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}) {
|
}) {
|
||||||
const {
|
const { rows, placeholder, max, defaultValue = '', disabled } = props
|
||||||
className,
|
|
||||||
rows,
|
|
||||||
placeholder,
|
|
||||||
max,
|
|
||||||
defaultValue = '',
|
|
||||||
onSend,
|
|
||||||
sending,
|
|
||||||
disabled,
|
|
||||||
} = props
|
|
||||||
|
|
||||||
const rowsClass = rows && `box-content min-h-[${LINE_HEIGHT * rows}em]`
|
const rowsClass = rows && `box-content min-h-[${LINE_HEIGHT * rows}em]`
|
||||||
|
|
||||||
|
@ -49,16 +36,10 @@ export function TextEditor(props: {
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sending && editor) onSend(editor.getJSON())
|
editor?.setEditable(!disabled)
|
||||||
}, [sending, editor, onSend])
|
}, [editor, disabled])
|
||||||
|
|
||||||
useEffect(() => {
|
return editor
|
||||||
editor?.setEditable(!disabled && !sending)
|
|
||||||
}, [editor, disabled, sending])
|
|
||||||
|
|
||||||
useWarnUnsavedChanges(!sending && editor != null && !editor.isEmpty)
|
|
||||||
|
|
||||||
return <EditorContent editor={editor} className={className} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function RichContent(props: { content: JSONContent }) {
|
function RichContent(props: { content: JSONContent }) {
|
||||||
|
|
|
@ -27,8 +27,8 @@ import { track } from 'web/lib/service/analytics'
|
||||||
import { GroupSelector } from 'web/components/groups/group-selector'
|
import { GroupSelector } from 'web/components/groups/group-selector'
|
||||||
import { CATEGORIES } from 'common/categories'
|
import { CATEGORIES } from 'common/categories'
|
||||||
import { User } from 'common/user'
|
import { User } from 'common/user'
|
||||||
import { TextEditor } from 'web/components/editor'
|
import { useTextEditor } from 'web/components/editor'
|
||||||
import { JSONContent } from '@tiptap/react'
|
import { EditorContent } from '@tiptap/react'
|
||||||
|
|
||||||
type NewQuestionParams = {
|
type NewQuestionParams = {
|
||||||
groupId?: string
|
groupId?: string
|
||||||
|
@ -163,8 +163,6 @@ export function NewContract(props: {
|
||||||
// get days from today until the end of this year:
|
// get days from today until the end of this year:
|
||||||
const daysLeftInTheYear = dayjs().endOf('year').diff(dayjs(), 'day')
|
const daysLeftInTheYear = dayjs().endOf('year').diff(dayjs(), 'day')
|
||||||
|
|
||||||
useWarnUnsavedChanges(!isSubmitting && Boolean(question))
|
|
||||||
|
|
||||||
const isValid =
|
const isValid =
|
||||||
(outcomeType === 'BINARY' ? initialProb >= 5 && initialProb <= 95 : true) &&
|
(outcomeType === 'BINARY' ? initialProb >= 5 && initialProb <= 95 : true) &&
|
||||||
question.length > 0 &&
|
question.length > 0 &&
|
||||||
|
@ -185,25 +183,39 @@ export function NewContract(props: {
|
||||||
min < initialValue &&
|
min < initialValue &&
|
||||||
initialValue < max))
|
initialValue < max))
|
||||||
|
|
||||||
|
const descriptionPlaceholder =
|
||||||
|
outcomeType === 'BINARY'
|
||||||
|
? `e.g. This question resolves to "YES" if they receive the majority of votes...`
|
||||||
|
: `e.g. I will choose the answer according to...`
|
||||||
|
|
||||||
|
const editor = useTextEditor({
|
||||||
|
rows: 3,
|
||||||
|
max: MAX_DESCRIPTION_LENGTH,
|
||||||
|
placeholder: descriptionPlaceholder,
|
||||||
|
disabled: isSubmitting,
|
||||||
|
})
|
||||||
|
|
||||||
|
useWarnUnsavedChanges(
|
||||||
|
!isSubmitting && (Boolean(question) || (editor != null && !editor.isEmpty))
|
||||||
|
)
|
||||||
|
|
||||||
function setCloseDateInDays(days: number) {
|
function setCloseDateInDays(days: number) {
|
||||||
const newCloseDate = dayjs().add(days, 'day').format('YYYY-MM-DD')
|
const newCloseDate = dayjs().add(days, 'day').format('YYYY-MM-DD')
|
||||||
setCloseDate(newCloseDate)
|
setCloseDate(newCloseDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
function submit() {
|
async function submit() {
|
||||||
// TODO: Tell users why their contract is invalid
|
// TODO: Tell users why their contract is invalid
|
||||||
if (!creator || !isValid) return
|
if (!creator || !isValid) return
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
}
|
|
||||||
|
|
||||||
async function onSubmit(description?: JSONContent) {
|
|
||||||
// TODO: add contract id to the group contractIds
|
// TODO: add contract id to the group contractIds
|
||||||
try {
|
try {
|
||||||
const result = await createMarket(
|
const result = await createMarket(
|
||||||
removeUndefinedProps({
|
removeUndefinedProps({
|
||||||
question,
|
question,
|
||||||
outcomeType,
|
outcomeType,
|
||||||
description,
|
description: editor?.getJSON(),
|
||||||
initialProb,
|
initialProb,
|
||||||
ante,
|
ante,
|
||||||
closeTime,
|
closeTime,
|
||||||
|
@ -232,11 +244,6 @@ export function NewContract(props: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const descriptionPlaceholder =
|
|
||||||
outcomeType === 'BINARY'
|
|
||||||
? `e.g. This question resolves to "YES" if they receive the majority of votes...`
|
|
||||||
: `e.g. I will choose the answer according to...`
|
|
||||||
|
|
||||||
if (!creator) return <></>
|
if (!creator) return <></>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -440,14 +447,7 @@ export function NewContract(props: {
|
||||||
<span className="mb-1">Description</span>
|
<span className="mb-1">Description</span>
|
||||||
<InfoTooltip text="Optional. Describe how you will resolve this question." />
|
<InfoTooltip text="Optional. Describe how you will resolve this question." />
|
||||||
</label>
|
</label>
|
||||||
<TextEditor
|
<EditorContent editor={editor} className="w-full" />
|
||||||
className="w-full"
|
|
||||||
rows={3}
|
|
||||||
max={MAX_DESCRIPTION_LENGTH}
|
|
||||||
placeholder={descriptionPlaceholder}
|
|
||||||
sending={isSubmitting}
|
|
||||||
onSend={onSubmit}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Spacer h={6} />
|
<Spacer h={6} />
|
||||||
|
|
Loading…
Reference in New Issue
Block a user