From e0634cea6d7c0a169829c04ed061f602b4fcfb1e Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 15 Sep 2022 18:19:22 -0500 Subject: [PATCH] Revert "Use %mention to embed a contract card in rich text editor (#869)" This reverts commit 140628692f9e09b6f2e582b31f88974dac581524. --- web/components/editor.tsx | 19 +---- .../editor/contract-mention-list.tsx | 68 ----------------- .../editor/contract-mention-suggestion.ts | 76 ------------------- web/components/editor/contract-mention.tsx | 41 ---------- web/hooks/use-contracts.ts | 9 +-- web/package.json | 1 - 6 files changed, 3 insertions(+), 211 deletions(-) delete mode 100644 web/components/editor/contract-mention-list.tsx delete mode 100644 web/components/editor/contract-mention-suggestion.ts delete mode 100644 web/components/editor/contract-mention.tsx diff --git a/web/components/editor.tsx b/web/components/editor.tsx index 95f18b3f..745fc3c5 100644 --- a/web/components/editor.tsx +++ b/web/components/editor.tsx @@ -21,8 +21,6 @@ import { FileUploadButton } from './file-upload-button' import { linkClass } from './site-link' import { mentionSuggestion } from './editor/mention-suggestion' import { DisplayMention } from './editor/mention' -import { contractMentionSuggestion } from './editor/contract-mention-suggestion' -import { DisplayContractMention } from './editor/contract-mention' import Iframe from 'common/util/tiptap-iframe' import TiptapTweet from './editor/tiptap-tweet' import { EmbedModal } from './editor/embed-modal' @@ -99,12 +97,7 @@ export function useTextEditor(props: { CharacterCount.configure({ limit: max }), simple ? DisplayImage : Image, DisplayLink, - DisplayMention.configure({ - suggestion: mentionSuggestion, - }), - DisplayContractMention.configure({ - suggestion: contractMentionSuggestion, - }), + DisplayMention.configure({ suggestion: mentionSuggestion }), Iframe, TiptapTweet, ], @@ -323,21 +316,13 @@ export function RichContent(props: { smallImage ? DisplayImage : Image, DisplayLink.configure({ openOnClick: false }), // stop link opening twice (browser still opens) DisplayMention, - DisplayContractMention.configure({ - // Needed to set a different PluginKey for Prosemirror - suggestion: contractMentionSuggestion, - }), Iframe, TiptapTweet, ], content, editable: false, }) - useEffect( - // Check isDestroyed here so hot reload works, see https://github.com/ueberdosis/tiptap/issues/1451#issuecomment-941988769 - () => void !editor?.isDestroyed && editor?.commands?.setContent(content), - [editor, content] - ) + useEffect(() => void editor?.commands?.setContent(content), [editor, content]) return } diff --git a/web/components/editor/contract-mention-list.tsx b/web/components/editor/contract-mention-list.tsx deleted file mode 100644 index bda9d2fc..00000000 --- a/web/components/editor/contract-mention-list.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { SuggestionProps } from '@tiptap/suggestion' -import clsx from 'clsx' -import { Contract } from 'common/contract' -import { forwardRef, useEffect, useImperativeHandle, useState } from 'react' -import { contractPath } from 'web/lib/firebase/contracts' -import { Avatar } from '../avatar' - -// copied from https://tiptap.dev/api/nodes/mention#usage -const M = forwardRef((props: SuggestionProps, ref) => { - const { items: contracts, command } = props - - const [selectedIndex, setSelectedIndex] = useState(0) - useEffect(() => setSelectedIndex(0), [contracts]) - - const submitUser = (index: number) => { - const contract = contracts[index] - if (contract) - command({ id: contract.id, label: contractPath(contract) } as any) - } - - const onUp = () => - setSelectedIndex((i) => (i + contracts.length - 1) % contracts.length) - const onDown = () => setSelectedIndex((i) => (i + 1) % contracts.length) - const onEnter = () => submitUser(selectedIndex) - - useImperativeHandle(ref, () => ({ - onKeyDown: ({ event }: any) => { - if (event.key === 'ArrowUp') { - onUp() - return true - } - if (event.key === 'ArrowDown') { - onDown() - return true - } - if (event.key === 'Enter') { - onEnter() - return true - } - return false - }, - })) - - return ( -
- {!contracts.length ? ( - No results... - ) : ( - contracts.map((contract, i) => ( - - )) - )} -
- ) -}) - -// Just to keep the formatting pretty -export { M as MentionList } diff --git a/web/components/editor/contract-mention-suggestion.ts b/web/components/editor/contract-mention-suggestion.ts deleted file mode 100644 index 79525cfc..00000000 --- a/web/components/editor/contract-mention-suggestion.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { MentionOptions } from '@tiptap/extension-mention' -import { ReactRenderer } from '@tiptap/react' -import { searchInAny } from 'common/util/parse' -import { orderBy } from 'lodash' -import tippy from 'tippy.js' -import { getCachedContracts } from 'web/hooks/use-contracts' -import { MentionList } from './contract-mention-list' -import { PluginKey } from 'prosemirror-state' - -type Suggestion = MentionOptions['suggestion'] - -const beginsWith = (text: string, query: string) => - text.toLocaleLowerCase().startsWith(query.toLocaleLowerCase()) - -// copied from https://tiptap.dev/api/nodes/mention#usage -// TODO: merge with mention-suggestion.ts? -export const contractMentionSuggestion: Suggestion = { - char: '%', - allowSpaces: true, - pluginKey: new PluginKey('contract-mention'), - items: async ({ query }) => - orderBy( - (await getCachedContracts()).filter((c) => - searchInAny(query, c.question) - ), - [(c) => [c.question].some((s) => beginsWith(s, query))], - ['desc', 'desc'] - ).slice(0, 5), - render: () => { - let component: ReactRenderer - let popup: ReturnType - return { - onStart: (props) => { - component = new ReactRenderer(MentionList, { - props, - editor: props.editor, - }) - if (!props.clientRect) { - return - } - - popup = tippy('body', { - getReferenceClientRect: props.clientRect as any, - appendTo: () => document.body, - content: component?.element, - showOnCreate: true, - interactive: true, - trigger: 'manual', - placement: 'bottom-start', - }) - }, - onUpdate(props) { - component?.updateProps(props) - - if (!props.clientRect) { - return - } - - popup?.[0].setProps({ - getReferenceClientRect: props.clientRect as any, - }) - }, - onKeyDown(props) { - if (props.event.key === 'Escape') { - popup?.[0].hide() - return true - } - return (component?.ref as any)?.onKeyDown(props) - }, - onExit() { - popup?.[0].destroy() - component?.destroy() - }, - } - }, -} diff --git a/web/components/editor/contract-mention.tsx b/web/components/editor/contract-mention.tsx deleted file mode 100644 index 9e967044..00000000 --- a/web/components/editor/contract-mention.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import Mention from '@tiptap/extension-mention' -import { - mergeAttributes, - NodeViewWrapper, - ReactNodeViewRenderer, -} from '@tiptap/react' -import clsx from 'clsx' -import { useContract } from 'web/hooks/use-contract' -import { ContractCard } from '../contract/contract-card' - -const name = 'contract-mention-component' - -const ContractMentionComponent = (props: any) => { - const contract = useContract(props.node.attrs.id) - - return ( - - {contract && ( - - )} - - ) -} - -/** - * Mention extension that renders React. See: - * https://tiptap.dev/guide/custom-extensions#extend-existing-extensions - * https://tiptap.dev/guide/node-views/react#render-a-react-component - */ -export const DisplayContractMention = Mention.extend({ - parseHTML: () => [{ tag: name }], - renderHTML: ({ HTMLAttributes }) => [name, mergeAttributes(HTMLAttributes)], - addNodeView: () => - ReactNodeViewRenderer(ContractMentionComponent, { - // On desktop, render cards below half-width so you can stack two - className: 'inline-block sm:w-[calc(50%-1rem)] sm:mr-1', - }), -}) diff --git a/web/hooks/use-contracts.ts b/web/hooks/use-contracts.ts index 87eefa38..1ea2f232 100644 --- a/web/hooks/use-contracts.ts +++ b/web/hooks/use-contracts.ts @@ -9,9 +9,8 @@ import { listenForNewContracts, getUserBetContracts, getUserBetContractsQuery, - listAllContracts, } from 'web/lib/firebase/contracts' -import { QueryClient, useQueryClient } from 'react-query' +import { useQueryClient } from 'react-query' import { MINUTE_MS } from 'common/util/time' export const useContracts = () => { @@ -24,12 +23,6 @@ export const useContracts = () => { return contracts } -const q = new QueryClient() -export const getCachedContracts = async () => - q.fetchQuery(['contracts'], () => listAllContracts(1000), { - staleTime: Infinity, - }) - export const useActiveContracts = () => { const [activeContracts, setActiveContracts] = useState< Contract[] | undefined diff --git a/web/package.json b/web/package.json index ba25a6e1..114ded1e 100644 --- a/web/package.json +++ b/web/package.json @@ -48,7 +48,6 @@ "nanoid": "^3.3.4", "next": "12.2.5", "node-fetch": "3.2.4", - "prosemirror-state": "1.4.1", "react": "17.0.2", "react-beautiful-dnd": "13.1.1", "react-confetti": "6.0.1",