diff --git a/web/components/editor.tsx b/web/components/editor.tsx
index 018d94a6..8f49c498 100644
--- a/web/components/editor.tsx
+++ b/web/components/editor.tsx
@@ -21,6 +21,8 @@ import { useMutation } from 'react-query'
import { linkClass } from './site-link'
import { DisplayMention } from './editor/mention'
import { DisplayContractMention } from './editor/contract-mention'
+import GridComponent from './editor/tiptap-grid-cards'
+
import Iframe from 'common/util/tiptap-iframe'
import TiptapTweet from './editor/tiptap-tweet'
import { EmbedModal } from './editor/embed-modal'
@@ -78,6 +80,7 @@ export const editorExtensions = (simple = false): Extensions => [
DisplayLink,
DisplayMention,
DisplayContractMention,
+ GridComponent,
Iframe,
TiptapTweet,
TiptapSpoiler.configure({
@@ -358,6 +361,7 @@ export function RichContent(props: {
DisplayLink.configure({ openOnClick: false }), // stop link opening twice (browser still opens)
DisplayMention,
DisplayContractMention,
+ GridComponent,
Iframe,
TiptapTweet,
TiptapSpoiler.configure({
diff --git a/web/components/editor/market-modal.tsx b/web/components/editor/market-modal.tsx
index 1e2c1482..ae0f50e1 100644
--- a/web/components/editor/market-modal.tsx
+++ b/web/components/editor/market-modal.tsx
@@ -1,7 +1,7 @@
import { Editor } from '@tiptap/react'
import { Contract } from 'common/contract'
import { SelectMarketsModal } from '../contract-select-modal'
-import { embedContractCode, embedContractGridCode } from '../share-embed-button'
+import { embedContractCode } from '../share-embed-button'
import { insertContent } from './utils'
export function MarketModal(props: {
@@ -15,7 +15,10 @@ export function MarketModal(props: {
if (contracts.length == 1) {
insertContent(editor, embedContractCode(contracts[0]))
} else if (contracts.length > 1) {
- insertContent(editor, embedContractGridCode(contracts))
+ insertContent(
+ editor,
+ ``
+ )
}
}
diff --git a/web/components/editor/tiptap-grid-cards.tsx b/web/components/editor/tiptap-grid-cards.tsx
new file mode 100644
index 00000000..48242ea2
--- /dev/null
+++ b/web/components/editor/tiptap-grid-cards.tsx
@@ -0,0 +1,55 @@
+import { mergeAttributes, Node } from '@tiptap/core'
+import React from 'react'
+import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'
+import { ContractsGrid } from '../contract/contracts-grid'
+
+import { useContractsFromIds } from 'web/hooks/use-contract'
+import { LoadingIndicator } from '../loading-indicator'
+
+export default Node.create({
+ name: 'gridCardsComponent',
+
+ group: 'block',
+
+ atom: true,
+
+ addAttributes() {
+ return {
+ contractIds: [],
+ }
+ },
+
+ parseHTML() {
+ return [
+ {
+ tag: 'grid-cards-component',
+ },
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['grid-cards-component', mergeAttributes(HTMLAttributes)]
+ },
+
+ addNodeView() {
+ return ReactNodeViewRenderer(GridComponent)
+ },
+})
+
+export function GridComponent(props: any) {
+ const contractIds = props.node.attrs.contractIds
+ const contracts = useContractsFromIds(contractIds.split(','))
+
+ return (
+
+ {contracts ? (
+
+ ) : (
+
+ )}
+
+ )
+}
diff --git a/web/hooks/use-contract.ts b/web/hooks/use-contract.ts
index acaf7730..2e7c4f84 100644
--- a/web/hooks/use-contract.ts
+++ b/web/hooks/use-contract.ts
@@ -3,10 +3,12 @@ import { useFirestoreDocumentData } from '@react-query-firebase/firestore'
import {
Contract,
contracts,
+ getContractFromId,
listenForContract,
} from 'web/lib/firebase/contracts'
import { useStateCheckEquality } from './use-state-check-equality'
import { doc, DocumentData } from 'firebase/firestore'
+import { useQuery } from 'react-query'
export const useContract = (contractId: string) => {
const result = useFirestoreDocumentData(
@@ -18,6 +20,17 @@ export const useContract = (contractId: string) => {
return result.isLoading ? undefined : result.data
}
+export const useContractsFromIds = (contractIds: string[]) => {
+ const contractResult = useQuery(['contracts', contractIds], () =>
+ Promise.all(contractIds.map(getContractFromId))
+ )
+ const contracts = contractResult.data?.filter(
+ (contract): contract is Contract => !!contract
+ )
+
+ return contractResult.isLoading ? undefined : contracts
+}
+
export const useContractWithPreload = (
initial: Contract | null | undefined
) => {