From aaa09f49c0d4953fdbd3f6bc12f0db84538c3622 Mon Sep 17 00:00:00 2001 From: FRC Date: Fri, 14 Oct 2022 16:21:54 +0100 Subject: [PATCH] New component to add arbitrary (but static) react embeds to posts programatically + midterms component (#1051) --- common/util/parse.ts | 1 + web/components/editor.tsx | 3 + .../editor/tiptap-static-react-embed.tsx | 44 ++++ web/components/midterms-maps.tsx | 212 ++++++++++++++++++ web/components/static-react-embed.tsx | 20 ++ 5 files changed, 280 insertions(+) create mode 100644 web/components/editor/tiptap-static-react-embed.tsx create mode 100644 web/components/midterms-maps.tsx create mode 100644 web/components/static-react-embed.tsx diff --git a/common/util/parse.ts b/common/util/parse.ts index 102a9e90..56314ae5 100644 --- a/common/util/parse.ts +++ b/common/util/parse.ts @@ -100,6 +100,7 @@ const stringParseExts = [ '[embed]' + node.attrs.src ? `(${node.attrs.src})` : '', }), skippableComponent('gridCardsComponent'), + skippableComponent('staticReactEmbedComponent'), TiptapTweet.extend({ renderText: () => '[tweet]' }), TiptapSpoiler.extend({ renderHTML: () => ['span', '[spoiler]', 0] }), ] diff --git a/web/components/editor.tsx b/web/components/editor.tsx index 0c3b4eec..146075a2 100644 --- a/web/components/editor.tsx +++ b/web/components/editor.tsx @@ -22,6 +22,7 @@ import { linkClass } from './site-link' import { DisplayMention } from './editor/mention' import { DisplayContractMention } from './editor/contract-mention' import GridComponent from './editor/tiptap-grid-cards' +import StaticReactEmbedComponent from './editor/tiptap-static-react-embed' import Iframe from 'common/util/tiptap-iframe' import TiptapTweet from './editor/tiptap-tweet' @@ -81,6 +82,7 @@ export const editorExtensions = (simple = false): Extensions => [ DisplayMention, DisplayContractMention, GridComponent, + StaticReactEmbedComponent, Iframe, TiptapTweet, TiptapSpoiler.configure({ @@ -363,6 +365,7 @@ export function RichContent(props: { DisplayMention, DisplayContractMention, GridComponent, + StaticReactEmbedComponent, Iframe, TiptapTweet, TiptapSpoiler.configure({ diff --git a/web/components/editor/tiptap-static-react-embed.tsx b/web/components/editor/tiptap-static-react-embed.tsx new file mode 100644 index 00000000..0dd819aa --- /dev/null +++ b/web/components/editor/tiptap-static-react-embed.tsx @@ -0,0 +1,44 @@ +import { mergeAttributes, Node } from '@tiptap/core' +import React from 'react' +import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react' +import { StaticReactEmbed } from '../static-react-embed' + +export default Node.create({ + name: 'staticReactEmbedComponent', + + group: 'block', + + atom: true, + + addAttributes() { + return { + embedName: '', + } + }, + + parseHTML() { + return [ + { + tag: 'static-react-embed-component', + }, + ] + }, + + renderHTML({ HTMLAttributes }) { + return ['static-react-embed-component', mergeAttributes(HTMLAttributes)] + }, + + addNodeView() { + return ReactNodeViewRenderer(StaticReactEmbedComponent) + }, +}) + +export function StaticReactEmbedComponent(props: any) { + const embedName = props.node.attrs.embedName + + return ( + + + + ) +} diff --git a/web/components/midterms-maps.tsx b/web/components/midterms-maps.tsx new file mode 100644 index 00000000..69b3a201 --- /dev/null +++ b/web/components/midterms-maps.tsx @@ -0,0 +1,212 @@ +import { useEffect } from 'react' +import { getContractFromSlug } from 'web/lib/firebase/contracts' +import { + StateElectionMap, + StateElectionMarket, +} from './usa-map/state-election-map' +import { useState } from 'react' +import { LoadingIndicator } from './loading-indicator' +import { CPMMBinaryContract } from 'common/contract' + +export function MidtermsMaps(props: { mapType: string }) { + const { mapType } = props + const [contracts, setContracts] = useState(null) + + useEffect(() => { + const getContracts = async () => { + if (props.mapType === 'senate') { + const senateContracts = await Promise.all( + senateMidterms.map((m) => + getContractFromSlug(m.slug).then((c) => c ?? null) + ) + ) + setContracts(senateContracts as CPMMBinaryContract[]) + } else if (props.mapType === 'governor') { + const governorContracts = await Promise.all( + governorMidterms.map((m) => + getContractFromSlug(m.slug).then((c) => c ?? null) + ) + ) + setContracts(governorContracts as CPMMBinaryContract[]) + } + } + getContracts() + }, [props.mapType, setContracts]) + + return contracts ? ( + + ) : ( + + ) +} + +const senateMidterms: StateElectionMarket[] = [ + { + state: 'AZ', + creatorUsername: 'BTE', + slug: 'will-blake-masters-win-the-arizona', + isWinRepublican: true, + }, + { + state: 'OH', + creatorUsername: 'BTE', + slug: 'will-jd-vance-win-the-ohio-senate-s', + isWinRepublican: true, + }, + { + state: 'WI', + creatorUsername: 'BTE', + slug: 'will-ron-johnson-be-reelected-in-th', + isWinRepublican: true, + }, + { + state: 'FL', + creatorUsername: 'BTE', + slug: 'will-marco-rubio-be-reelected-to-th', + isWinRepublican: true, + }, + { + state: 'PA', + creatorUsername: 'MattP', + slug: 'will-dr-oz-be-elected-to-the-us-sen', + isWinRepublican: true, + }, + { + state: 'GA', + creatorUsername: 'NcyRocks', + slug: 'will-a-democrat-win-the-2022-us-sen-3d2432ba6d79', + isWinRepublican: false, + }, + { + state: 'NV', + creatorUsername: 'NcyRocks', + slug: 'will-a-democrat-win-the-2022-us-sen', + isWinRepublican: false, + }, + { + state: 'NC', + creatorUsername: 'NcyRocks', + slug: 'will-a-democrat-win-the-2022-us-sen-6f1a901e1fcf', + isWinRepublican: false, + }, + { + state: 'NH', + creatorUsername: 'NcyRocks', + slug: 'will-a-democrat-win-the-2022-us-sen-23194a72f1b7', + isWinRepublican: false, + }, + { + state: 'UT', + creatorUsername: 'SG', + slug: 'will-mike-lee-win-the-2022-utah-sen', + isWinRepublican: true, + }, + { + state: 'CO', + creatorUsername: 'SG', + slug: 'will-michael-bennet-win-the-2022-co', + isWinRepublican: false, + }, +] + +const governorMidterms: StateElectionMarket[] = [ + { + state: 'TX', + creatorUsername: 'LarsDoucet', + slug: 'republicans-will-win-the-2022-texas', + isWinRepublican: true, + }, + { + state: 'GA', + creatorUsername: 'MattP', + slug: 'will-stacey-abrams-win-the-2022-geo', + isWinRepublican: false, + }, + { + state: 'FL', + creatorUsername: 'Tetraspace', + slug: 'if-charlie-crist-is-the-democratic', + isWinRepublican: false, + }, + { + state: 'PA', + creatorUsername: 'JonathanMast', + slug: 'will-josh-shapiro-win-the-2022-penn', + isWinRepublican: false, + }, + { + state: 'PA', + creatorUsername: 'JonathanMast', + slug: 'will-josh-shapiro-win-the-2022-penn', + isWinRepublican: false, + }, + { + state: 'CO', + creatorUsername: 'ScottLawrence', + slug: 'will-jared-polis-be-reelected-as-co', + isWinRepublican: false, + }, + { + state: 'OR', + creatorUsername: 'Tetraspace', + slug: 'if-tina-kotek-is-the-2022-democrati', + isWinRepublican: false, + }, + { + state: 'MD', + creatorUsername: 'Tetraspace', + slug: 'if-wes-moore-is-the-2022-democratic', + isWinRepublican: false, + }, + { + state: 'AK', + creatorUsername: 'SG', + slug: 'will-a-republican-win-the-2022-alas', + isWinRepublican: true, + }, + { + state: 'AZ', + creatorUsername: 'SG', + slug: 'will-a-republican-win-the-2022-ariz', + isWinRepublican: true, + }, + { + state: 'AZ', + creatorUsername: 'SG', + slug: 'will-a-republican-win-the-2022-ariz', + isWinRepublican: true, + }, + { + state: 'WI', + creatorUsername: 'SG', + slug: 'will-a-democrat-win-the-2022-wiscon', + isWinRepublican: false, + }, + { + state: 'NV', + creatorUsername: 'SG', + slug: 'will-a-democrat-win-the-2022-nevada', + isWinRepublican: false, + }, + { + state: 'KS', + creatorUsername: 'SG', + slug: 'will-a-democrat-win-the-2022-kansas', + isWinRepublican: false, + }, + { + state: 'NV', + creatorUsername: 'SG', + slug: 'will-a-democrat-win-the-2022-new-me', + isWinRepublican: false, + }, + { + state: 'ME', + creatorUsername: 'SG', + slug: 'will-a-democrat-win-the-2022-maine', + isWinRepublican: false, + }, +] diff --git a/web/components/static-react-embed.tsx b/web/components/static-react-embed.tsx new file mode 100644 index 00000000..afc18e79 --- /dev/null +++ b/web/components/static-react-embed.tsx @@ -0,0 +1,20 @@ +import { useState, useEffect } from 'react' +import { MidtermsMaps } from './midterms-maps' + +export function StaticReactEmbed(props: { embedName: string }) { + const { embedName } = props + const [embed, setEmbed] = useState(null) + + useEffect(() => { + const governorMidtermsMap = + const senateMidtermsMap = + + if (embedName === 'governor-midterms-map') { + setEmbed(governorMidtermsMap) + } else if (embedName === 'senate-midterms-map') { + setEmbed(senateMidtermsMap) + } + }, [embedName, setEmbed]) + + return
{embed}
+}