Add embedded ContractGrid to Posts (#822)

* Add embedded market grids

* Hacky way to set height

I haven't figured out a way yet to get the height of the actual iframe's content, so I did some bad estimate for now to unblock shipping the feature, while I continue investigating.
This commit is contained in:
FRC 2022-09-01 17:47:45 +01:00 committed by GitHub
parent 7310cf3d4a
commit 96be4e8992
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 10 deletions

View File

@ -48,6 +48,9 @@ export default Node.create<IframeOptions>({
frameborder: { frameborder: {
default: 0, default: 0,
}, },
height: {
default: 0,
},
allowfullscreen: { allowfullscreen: {
default: this.options.allowFullscreen, default: this.options.allowFullscreen,
parseHTML: () => this.options.allowFullscreen, parseHTML: () => this.options.allowFullscreen,
@ -60,6 +63,11 @@ export default Node.create<IframeOptions>({
}, },
renderHTML({ HTMLAttributes }) { renderHTML({ HTMLAttributes }) {
this.options.HTMLAttributes.style =
this.options.HTMLAttributes.style +
' height: ' +
HTMLAttributes.height +
';'
return [ return [
'div', 'div',
this.options.HTMLAttributes, this.options.HTMLAttributes,

View File

@ -27,6 +27,7 @@ export function ContractsGrid(props: {
} }
highlightOptions?: ContractHighlightOptions highlightOptions?: ContractHighlightOptions
trackingPostfix?: string trackingPostfix?: string
breakpointColumns?: { [key: string]: number }
}) { }) {
const { const {
contracts, contracts,
@ -67,7 +68,7 @@ export function ContractsGrid(props: {
<Col className="gap-8"> <Col className="gap-8">
<Masonry <Masonry
// Show only 1 column on tailwind's md breakpoint (768px) // Show only 1 column on tailwind's md breakpoint (768px)
breakpointCols={{ default: 2, 768: 1 }} breakpointCols={props.breakpointColumns ?? { default: 2, 768: 1 }}
className="-ml-4 flex w-auto" className="-ml-4 flex w-auto"
columnClassName="pl-4 bg-clip-padding" columnClassName="pl-4 bg-clip-padding"
> >

View File

@ -7,7 +7,7 @@ import { Col } from '../layout/col'
import { Modal } from '../layout/modal' import { Modal } from '../layout/modal'
import { Row } from '../layout/row' import { Row } from '../layout/row'
import { LoadingIndicator } from '../loading-indicator' import { LoadingIndicator } from '../loading-indicator'
import { embedCode } from '../share-embed-button' import { embedContractCode, embedContractGridCode } from '../share-embed-button'
import { insertContent } from './utils' import { insertContent } from './utils'
export function MarketModal(props: { export function MarketModal(props: {
@ -28,7 +28,11 @@ export function MarketModal(props: {
async function doneAddingContracts() { async function doneAddingContracts() {
setLoading(true) setLoading(true)
insertContent(editor, ...contracts.map(embedCode)) if (contracts.length == 1) {
insertContent(editor, embedContractCode(contracts[0]))
} else if (contracts.length > 1) {
insertContent(editor, embedContractGridCode(contracts))
}
setLoading(false) setLoading(false)
setOpen(false) setOpen(false)
setContracts([]) setContracts([])
@ -42,9 +46,14 @@ export function MarketModal(props: {
{!loading && ( {!loading && (
<Row className="grow justify-end gap-4"> <Row className="grow justify-end gap-4">
{contracts.length > 0 && ( {contracts.length == 1 && (
<Button onClick={doneAddingContracts} color={'indigo'}> <Button onClick={doneAddingContracts} color={'indigo'}>
Embed {contracts.length} question Embed 1 question
</Button>
)}
{contracts.length > 1 && (
<Button onClick={doneAddingContracts} color={'indigo'}>
Embed grid of {contracts.length} question
{contracts.length > 1 && 's'} {contracts.length > 1 && 's'}
</Button> </Button>
)} )}

View File

@ -9,11 +9,18 @@ import { DOMAIN } from 'common/envs/constants'
import { copyToClipboard } from 'web/lib/util/copy' import { copyToClipboard } from 'web/lib/util/copy'
import { track } from 'web/lib/service/analytics' import { track } from 'web/lib/service/analytics'
export function embedCode(contract: Contract) { export function embedContractCode(contract: Contract) {
const title = contract.question const title = contract.question
const src = `https://${DOMAIN}/embed${contractPath(contract)}` const src = `https://${DOMAIN}/embed${contractPath(contract)}`
return `<iframe src="${src}" title="${title}" frameborder="0"></iframe>`
}
return `<iframe width="560" height="405" src="${src}" title="${title}" frameborder="0"></iframe>` export function embedContractGridCode(contracts: Contract[]) {
const height = (contracts.length - (contracts.length % 2)) * 100 + 'px'
const src = `http://${DOMAIN}/embed/grid/${contracts
.map((c) => c.slug)
.join('/')}`
return `<iframe height="${height}" src="${src}" title="Grid of contracts" frameborder="0"></iframe>`
} }
export function ShareEmbedButton(props: { contract: Contract }) { export function ShareEmbedButton(props: { contract: Contract }) {
@ -26,7 +33,7 @@ export function ShareEmbedButton(props: { contract: Contract }) {
as="div" as="div"
className="relative z-10 flex-shrink-0" className="relative z-10 flex-shrink-0"
onMouseUp={() => { onMouseUp={() => {
copyToClipboard(embedCode(contract)) copyToClipboard(embedContractCode(contract))
toast.success('Embed code copied!', { toast.success('Embed code copied!', {
icon: codeIcon, icon: codeIcon,
}) })

View File

@ -41,7 +41,7 @@ export default function CreatePost() {
return ( return (
<Page> <Page>
<div className="mx-auto w-full max-w-2xl"> <div className="mx-auto w-full max-w-3xl">
<div className="rounded-lg px-6 py-4 sm:py-0"> <div className="rounded-lg px-6 py-4 sm:py-0">
<Title className="!mt-0" text="Create a post" /> <Title className="!mt-0" text="Create a post" />
<form> <form>

View File

@ -0,0 +1,37 @@
import React from 'react'
import { Contract, getContractFromSlug } from 'web/lib/firebase/contracts'
import { ContractsGrid } from 'web/components/contract/contracts-grid'
export async function getStaticProps(props: { params: { slugs: string[] } }) {
const { slugs } = props.params
const contracts = (await Promise.all(
slugs.map((slug) =>
getContractFromSlug(slug) != null ? getContractFromSlug(slug) : []
)
)) as Contract[]
return {
props: {
contracts,
},
revalidate: 60, // regenerate after a minute
}
}
export async function getStaticPaths() {
return { paths: [], fallback: 'blocking' }
}
export default function ContractGridPage(props: { contracts: Contract[] }) {
const { contracts } = props
return (
<>
<ContractsGrid
contracts={contracts}
breakpointColumns={{ default: 2, 650: 1 }}
/>
</>
)
}