From 5e8decfa4e3ece1edf70a048e9380b7bebed6b4a Mon Sep 17 00:00:00 2001 From: James Grugett Date: Thu, 7 Apr 2022 15:52:54 -0500 Subject: [PATCH] Move tweet, embed buttons plus communities and tags into a market info dialog --- web/components/contract-card.tsx | 32 ++------- web/components/contract-info-dialog.tsx | 88 +++++++++++++++++++++++++ web/components/contract-overview.tsx | 26 +------- web/components/share-embed-button.tsx | 20 +++--- web/components/tags-input.tsx | 2 +- web/components/tags-list.tsx | 23 ++++--- web/components/tweet-button.tsx | 12 ++-- web/pages/[username]/[contractSlug].tsx | 5 -- 8 files changed, 125 insertions(+), 83 deletions(-) create mode 100644 web/components/contract-info-dialog.tsx diff --git a/web/components/contract-card.tsx b/web/components/contract-card.tsx index f1a1c3b2..80e70c41 100644 --- a/web/components/contract-card.tsx +++ b/web/components/contract-card.tsx @@ -19,9 +19,8 @@ import { fromNow } from '../lib/util/time' import { Avatar } from './avatar' import { Spacer } from './layout/spacer' import { useState } from 'react' -import { TweetButton } from './tweet-button' import { getProbability } from '../../common/calculate' -import { ShareEmbedButton } from './share-embed-button' +import { ContractInfoDialog } from './contract-info-dialog' export function ContractCard(props: { contract: Contract @@ -179,11 +178,9 @@ export function ContractDetails(props: { const { closeTime, creatorName, creatorUsername } = contract const { volumeLabel, createdDate, resolvedDate } = contractMetrics(contract) - const tweetText = getTweetText(contract, !!isCreator) - return ( - + - - +
+ )} @@ -331,24 +328,3 @@ function EditableCloseDate(props: { ) } - -const getTweetText = (contract: Contract, isCreator: boolean) => { - const { question, creatorName, resolution, outcomeType } = contract - const isBinary = outcomeType === 'BINARY' - - const tweetQuestion = isCreator - ? question - : `${question} Asked by ${creatorName}.` - const tweetDescription = resolution - ? `Resolved ${resolution}!` - : isBinary - ? `Currently ${getBinaryProbPercent( - contract - )} chance, place your bets here:` - : `Submit your own answer:` - - const timeParam = `${Date.now()}`.substring(7) - const url = `https://manifold.markets${contractPath(contract)}?t=${timeParam}` - - return `${tweetQuestion}\n\n${tweetDescription}\n\n${url}` -} diff --git a/web/components/contract-info-dialog.tsx b/web/components/contract-info-dialog.tsx new file mode 100644 index 00000000..e000bf71 --- /dev/null +++ b/web/components/contract-info-dialog.tsx @@ -0,0 +1,88 @@ +import { DotsHorizontalIcon } from '@heroicons/react/outline' +import clsx from 'clsx' +import { useState } from 'react' +import { Contract } from '../../common/contract' +import { useFoldsWithTags } from '../hooks/use-fold' +import { useUser } from '../hooks/use-user' +import { contractPath, getBinaryProbPercent } from '../lib/firebase/contracts' +import { Col } from './layout/col' +import { Modal } from './layout/modal' +import { Row } from './layout/row' +import { ShareEmbedButton } from './share-embed-button' +import { TagsInput } from './tags-input' +import { FoldTagList } from './tags-list' +import { Title } from './title' +import { TweetButton } from './tweet-button' + +export function ContractInfoDialog(props: { contract: Contract }) { + const { contract } = props + + const [open, setOpen] = useState(false) + + const user = useUser() + + const folds = (useFoldsWithTags(contract.tags) ?? []).filter( + (fold) => fold.followCount > 1 || user?.id === fold.curatorId + ) + + return ( + <> + + + + + + + <div className="text-gray-500">Share</div> + <Row className="justify-start gap-4"> + <TweetButton + className="self-start" + tweetText={getTweetText(contract, false)} + /> + <ShareEmbedButton contract={contract} /> + </Row> + <div /> + <div className="text-gray-500">Communities</div> + <FoldTagList folds={folds} noLabel /> + <div /> + + <div className="text-gray-500">Tags</div> + <TagsInput contract={contract} /> + + <div /> + </Col> + </Modal> + </> + ) +} + +const getTweetText = (contract: Contract, isCreator: boolean) => { + const { question, creatorName, resolution, outcomeType } = contract + const isBinary = outcomeType === 'BINARY' + + const tweetQuestion = isCreator + ? question + : `${question}\nAsked by ${creatorName}.` + const tweetDescription = resolution + ? `Resolved ${resolution}!` + : isBinary + ? `Currently ${getBinaryProbPercent( + contract + )} chance, place your bets here:` + : `Submit your own answer:` + + const timeParam = `${Date.now()}`.substring(7) + const url = `https://manifold.markets${contractPath(contract)}?t=${timeParam}` + + return `${tweetQuestion}\n\n${tweetDescription}\n\n${url}` +} diff --git a/web/components/contract-overview.tsx b/web/components/contract-overview.tsx index c94dbaf5..328bfc69 100644 --- a/web/components/contract-overview.tsx +++ b/web/components/contract-overview.tsx @@ -9,10 +9,7 @@ import clsx from 'clsx' import { ContractDetails, ResolutionOrChance } from './contract-card' import { Bet } from '../../common/bet' import { Comment } from '../../common/comment' -import { RevealableTagsInput, TagsInput } from './tags-input' import BetRow from './bet-row' -import { Fold } from '../../common/fold' -import { FoldTagList } from './tags-list' import { ContractActivity } from './feed/contract-activity' import { AnswersGraph } from './answers/answers-graph' import { DPM, FreeResponse, FullContract } from '../../common/contract' @@ -21,11 +18,10 @@ export const ContractOverview = (props: { contract: Contract bets: Bet[] comments: Comment[] - folds: Fold[] children?: any className?: string }) => { - const { contract, bets, comments, folds, children, className } = props + const { contract, bets, comments, children, className } = props const { question, resolution, creatorId, outcomeType } = contract const user = useUser() @@ -75,26 +71,6 @@ export const ContractOverview = (props: { {children} - <Row className="mt-6 hidden items-center justify-between gap-4 sm:flex"> - {folds.length === 0 ? ( - <TagsInput className={clsx('mx-4')} contract={contract} /> - ) : ( - <FoldTagList folds={folds} /> - )} - </Row> - - <Col className="mt-6 gap-4 sm:hidden"> - {folds.length === 0 ? ( - <TagsInput contract={contract} /> - ) : ( - <FoldTagList folds={folds} /> - )} - </Col> - - {folds.length > 0 && ( - <RevealableTagsInput className="mt-4" contract={contract} /> - )} - <Spacer h={12} /> <ContractActivity diff --git a/web/components/share-embed-button.tsx b/web/components/share-embed-button.tsx index b63dcd60..eeed7d44 100644 --- a/web/components/share-embed-button.tsx +++ b/web/components/share-embed-button.tsx @@ -6,23 +6,23 @@ import { contractPath } from '../lib/firebase/contracts' import { DOMAIN } from '../../common/envs/constants' import { copyToClipboard } from '../lib/util/copy' +function copyEmbedCode(contract: Contract) { + const title = contract.question + const src = `https://${DOMAIN}/embed${contractPath(contract)}` + + const embedCode = `<iframe width="560" height="405" src="${src}" title="${title}" frameborder="0"></iframe>` + + copyToClipboard(embedCode) +} + export function ShareEmbedButton(props: { contract: Contract }) { const { contract } = props - const copyEmbed = () => { - const title = contract.question - const src = `https://${DOMAIN}/embed${contractPath(contract)}` - - const embedCode = `<iframe width="560" height="405" src="${src}" title="${title}" frameborder="0"></iframe>` - - copyToClipboard(embedCode) - } - return ( <Menu as="div" className="relative z-10 flex-shrink-0" - onMouseUp={copyEmbed} + onMouseUp={() => copyEmbedCode(contract)} > <Menu.Button className="btn btn-xs normal-case" diff --git a/web/components/tags-input.tsx b/web/components/tags-input.tsx index 947ad66b..83c6bbb1 100644 --- a/web/components/tags-input.tsx +++ b/web/components/tags-input.tsx @@ -27,7 +27,7 @@ export function TagsInput(props: { contract: Contract; className?: string }) { return ( <Col className={clsx('gap-4', className)}> - <TagsList tags={newTags} /> + <TagsList tags={newTags} noLabel /> <Row className="items-center gap-4"> <input diff --git a/web/components/tags-list.tsx b/web/components/tags-list.tsx index 7e02d5f9..1f22859a 100644 --- a/web/components/tags-list.tsx +++ b/web/components/tags-list.tsx @@ -1,4 +1,5 @@ import clsx from 'clsx' +import { Col } from './layout/col' import { Row } from './layout/row' import { SiteLink } from './site-link' @@ -70,15 +71,17 @@ export function FoldTagList(props: { }) { const { folds, noLabel, className } = props return ( - <Row className={clsx('flex-wrap items-center gap-2', className)}> - {folds.length > 0 && ( - <> - {!noLabel && <div className="mr-1 text-gray-500">Communities</div>} - {folds.map((fold) => ( - <FoldTag key={fold.slug} fold={fold} /> - ))} - </> - )} - </Row> + <Col className="gap-2"> + {!noLabel && <div className="mr-1 text-gray-500">Communities</div>} + <Row className={clsx('flex-wrap items-center gap-2', className)}> + {folds.length > 0 && ( + <> + {folds.map((fold) => ( + <FoldTag key={fold.slug} fold={fold} /> + ))} + </> + )} + </Row> + </Col> ) } diff --git a/web/components/tweet-button.tsx b/web/components/tweet-button.tsx index cbc242dc..44f32ab9 100644 --- a/web/components/tweet-button.tsx +++ b/web/components/tweet-button.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx' -export function TweetButton(props: { className?: string; tweetText?: string }) { +export function TweetButton(props: { className?: string; tweetText: string }) { const { tweetText, className } = props return ( @@ -11,9 +11,7 @@ export function TweetButton(props: { className?: string; tweetText?: string }) { border: '2px solid #1da1f2', color: '#1da1f2', }} - href={`https://twitter.com/intent/tweet?text=${encodeURIComponent( - tweetText ?? '' - )}`} + href={getTweetHref(tweetText)} target="_blank" > <img className="mr-2" src={'/twitter-logo.svg'} width={15} height={15} /> @@ -21,3 +19,9 @@ export function TweetButton(props: { className?: string; tweetText?: string }) { </a> ) } + +function getTweetHref(tweetText: string) { + return `https://twitter.com/intent/tweet?text=${encodeURIComponent( + tweetText ?? '' + )}` +} diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx index f3887605..73d96fdb 100644 --- a/web/pages/[username]/[contractSlug].tsx +++ b/web/pages/[username]/[contractSlug].tsx @@ -103,10 +103,6 @@ export default function ContractPage(props: { comments.sort((c1, c2) => c1.createdTime - c2.createdTime) bets.sort((bet1, bet2) => bet1.createdTime - bet2.createdTime) - const folds = (useFoldsWithTags(contract?.tags) ?? props.folds).filter( - (fold) => fold.followCount > 1 || user?.id === fold.curatorId - ) - if (!contract) { return <Custom404 /> } @@ -146,7 +142,6 @@ export default function ContractPage(props: { contract={contract} bets={bets ?? []} comments={comments ?? []} - folds={folds} > {contract.outcomeType === 'FREE_RESPONSE' && ( <>