From a10605e74c26580b6a5df7160939e913645c74eb Mon Sep 17 00:00:00 2001 From: Marshall Polaris Date: Wed, 21 Sep 2022 00:02:10 -0700 Subject: [PATCH 01/60] More work on contract page and tabs (#912) * Consolidate comment thread component code * Move `visibleBets` work down into bets tab * Remove unnecessary cruft from contract page props * Don't load all comments in contract page static props anymore * Tidy up props a bit * Memoize bets tab * Memoize recommended contracts widget --- .../contract/contract-leaderboard.tsx | 12 +- web/components/contract/contract-tabs.tsx | 194 +++++++----------- web/pages/[username]/[contractSlug].tsx | 114 ++++------ web/pages/embed/[username]/[contractSlug].tsx | 19 +- 4 files changed, 125 insertions(+), 214 deletions(-) diff --git a/web/components/contract/contract-leaderboard.tsx b/web/components/contract/contract-leaderboard.tsx index 4d25ffa4..6cd2ae62 100644 --- a/web/components/contract/contract-leaderboard.tsx +++ b/web/components/contract/contract-leaderboard.tsx @@ -1,10 +1,10 @@ import { Bet } from 'common/bet' -import { ContractComment } from 'common/comment' import { resolvedPayout } from 'common/calculate' import { Contract } from 'common/contract' import { formatMoney } from 'common/util/format' import { groupBy, mapValues, sumBy, sortBy, keyBy } from 'lodash' import { useState, useMemo, useEffect } from 'react' +import { useComments } from 'web/hooks/use-comments' import { listUsers, User } from 'web/lib/firebase/users' import { FeedBet } from '../feed/feed-bets' import { FeedComment } from '../feed/feed-comments' @@ -61,12 +61,10 @@ export function ContractLeaderboard(props: { ) : null } -export function ContractTopTrades(props: { - contract: Contract - bets: Bet[] - comments: ContractComment[] -}) { - const { contract, bets, comments } = props +export function ContractTopTrades(props: { contract: Contract; bets: Bet[] }) { + const { contract, bets } = props + // todo: this stuff should be calced in DB at resolve time + const comments = useComments(contract.id) const commentsById = keyBy(comments, 'id') const betsById = keyBy(bets, 'id') diff --git a/web/components/contract/contract-tabs.tsx b/web/components/contract/contract-tabs.tsx index 245a8d7d..008eb584 100644 --- a/web/components/contract/contract-tabs.tsx +++ b/web/components/contract/contract-tabs.tsx @@ -5,19 +5,19 @@ import { FeedBet } from '../feed/feed-bets' import { FeedLiquidity } from '../feed/feed-liquidity' import { FeedAnswerCommentGroup } from '../feed/feed-answer-comment-group' import { FeedCommentThread, ContractCommentInput } from '../feed/feed-comments' -import { CommentTipMap } from 'web/hooks/use-tip-txns' import { groupBy, sortBy } from 'lodash' import { Bet } from 'common/bet' -import { Contract, FreeResponseContract } from 'common/contract' -import { ContractComment } from 'common/comment' -import { PAST_BETS, User } from 'common/user' +import { Contract } from 'common/contract' +import { PAST_BETS } from 'common/user' import { ContractBetsTable, BetsSummary } from '../bets-list' import { Spacer } from '../layout/spacer' import { Tabs } from '../layout/tabs' import { Col } from '../layout/col' +import { LoadingIndicator } from 'web/components/loading-indicator' import { useComments } from 'web/hooks/use-comments' import { useLiquidity } from 'web/hooks/use-liquidity' import { useTipTxns } from 'web/hooks/use-tip-txns' +import { useUser } from 'web/hooks/use-user' import { capitalize } from 'lodash' import { DEV_HOUSE_LIQUIDITY_PROVIDER_ID, @@ -25,21 +25,13 @@ import { } from 'common/antes' import { useIsMobile } from 'web/hooks/use-is-mobile' -export function ContractTabs(props: { - contract: Contract - user: User | null | undefined - bets: Bet[] - comments: ContractComment[] -}) { - const { contract, user, bets, comments } = props +export function ContractTabs(props: { contract: Contract; bets: Bet[] }) { + const { contract, bets } = props const isMobile = useIsMobile() - + const user = useUser() const userBets = user && bets.filter((bet) => !bet.isAnte && bet.userId === user.id) - const visibleBets = bets.filter( - (bet) => !bet.isAnte && !bet.isRedemption && bet.amount !== 0 - ) const yourTrades = (
@@ -61,15 +53,11 @@ export function ContractTabs(props: { tabs={[ { title: 'Comments', - content: ( - - ), + content: , }, { title: capitalize(PAST_BETS), - content: ( - - ), + content: , }, ...(!user || !userBets?.length ? [] @@ -86,46 +74,87 @@ export function ContractTabs(props: { const CommentsTabContent = memo(function CommentsTabContent(props: { contract: Contract - comments: ContractComment[] }) { - const { contract, comments } = props + const { contract } = props const tips = useTipTxns({ contractId: contract.id }) - const updatedComments = useComments(contract.id) ?? comments + const comments = useComments(contract.id) + if (comments == null) { + return + } if (contract.outcomeType === 'FREE_RESPONSE') { + const generalComments = comments.filter( + (c) => c.answerOutcome === undefined && c.betId === undefined + ) + const sortedAnswers = sortBy( + contract.answers, + (a) => -getOutcomeProbability(contract, a.id) + ) + const commentsByOutcome = groupBy( + comments, + (c) => c.answerOutcome ?? c.betOutcome ?? '_' + ) return ( <> - + {sortedAnswers.map((answer) => ( +
+
+ ))}
General Comments
- - comment.answerOutcome === undefined && - comment.betId === undefined - )} - tips={tips} - /> + + {generalComments.map((comment) => ( + + ))} ) } else { + const commentsByParent = groupBy(comments, (c) => c.replyToCommentId ?? '_') + const topLevelComments = commentsByParent['_'] ?? [] return ( - + <> + + {sortBy(topLevelComments, (c) => -c.createdTime).map((parent) => ( + c.createdTime + )} + tips={tips} + /> + ))} + ) } }) -function ContractBetsActivity(props: { contract: Contract; bets: Bet[] }) { +const BetsTabContent = memo(function BetsTabContent(props: { + contract: Contract + bets: Bet[] +}) { const { contract, bets } = props const [page, setPage] = useState(0) const ITEMS_PER_PAGE = 50 @@ -133,6 +162,9 @@ function ContractBetsActivity(props: { contract: Contract; bets: Bet[] }) { const end = start + ITEMS_PER_PAGE const lps = useLiquidity(contract.id) ?? [] + const visibleBets = bets.filter( + (bet) => !bet.isAnte && !bet.isRedemption && bet.amount !== 0 + ) const visibleLps = lps.filter( (l) => !l.isAnte && @@ -142,7 +174,7 @@ function ContractBetsActivity(props: { contract: Contract; bets: Bet[] }) { ) const items = [ - ...bets.map((bet) => ({ + ...visibleBets.map((bet) => ({ type: 'bet' as const, id: bet.id + '-' + bet.isSold, bet, @@ -184,74 +216,4 @@ function ContractBetsActivity(props: { contract: Contract; bets: Bet[] }) { /> ) -} - -function ContractCommentsActivity(props: { - contract: Contract - comments: ContractComment[] - tips: CommentTipMap -}) { - const { contract, comments, tips } = props - const commentsByParentId = groupBy(comments, (c) => c.replyToCommentId ?? '_') - const topLevelComments = sortBy( - commentsByParentId['_'] ?? [], - (c) => -c.createdTime - ) - - return ( - <> - - {topLevelComments.map((parent) => ( - c.createdTime - )} - tips={tips} - /> - ))} - - ) -} - -function FreeResponseContractCommentsActivity(props: { - contract: FreeResponseContract - comments: ContractComment[] - tips: CommentTipMap -}) { - const { contract, comments, tips } = props - - const sortedAnswers = sortBy( - contract.answers, - (answer) => -getOutcomeProbability(contract, answer.number.toString()) - ) - const commentsByOutcome = groupBy( - comments, - (c) => c.answerOutcome ?? c.betOutcome ?? '_' - ) - - return ( - <> - {sortedAnswers.map((answer) => ( -
-
- ))} - - ) -} +}) diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx index 3682e700..38df2fbf 100644 --- a/web/pages/[username]/[contractSlug].tsx +++ b/web/pages/[username]/[contractSlug].tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react' +import React, { memo, useEffect, useMemo, useState } from 'react' import { ArrowLeftIcon } from '@heroicons/react/outline' import { useContractWithPreload } from 'web/hooks/use-contract' @@ -17,7 +17,6 @@ import { import { SEO } from 'web/components/SEO' import { Page } from 'web/components/page' import { Bet, listAllBets } from 'web/lib/firebase/bets' -import { listAllComments } from 'web/lib/firebase/comments' import Custom404 from '../404' import { AnswersPanel } from 'web/components/answers/answers-panel' import { fromPropz, usePropz } from 'web/hooks/use-propz' @@ -32,8 +31,6 @@ import { CPMMBinaryContract } from 'common/contract' import { AlertBox } from 'web/components/alert-box' import { useTracking } from 'web/hooks/use-tracking' import { useSaveReferral } from 'web/hooks/use-save-referral' -import { User } from 'common/user' -import { ContractComment } from 'common/comment' import { getOpenGraphProps } from 'common/contract-details' import { ContractDescription } from 'web/components/contract/contract-description' import { @@ -54,25 +51,14 @@ export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { username: string; contractSlug: string } }) { - const { username, contractSlug } = props.params + const { contractSlug } = props.params const contract = (await getContractFromSlug(contractSlug)) || null const contractId = contract?.id - - const [bets, comments] = await Promise.all([ - contractId ? listAllBets(contractId) : [], - contractId ? listAllComments(contractId) : [], - ]) + const bets = contractId ? await listAllBets(contractId) : [] return { - props: { - contract, - username, - slug: contractSlug, - // Limit the data sent to the client. Client will still load all bets and comments directly. - bets: bets.slice(0, 5000), - comments: comments.slice(0, 1000), - }, - + // Limit the data sent to the client. Client will still load all bets directly. + props: { contract, bets: bets.slice(0, 5000) }, revalidate: 5, // regenerate after five seconds } } @@ -83,21 +69,11 @@ export async function getStaticPaths() { export default function ContractPage(props: { contract: Contract | null - username: string bets: Bet[] - comments: ContractComment[] - slug: string backToHome?: () => void }) { - props = usePropz(props, getStaticPropz) ?? { - contract: null, - username: '', - comments: [], - bets: [], - slug: '', - } + props = usePropz(props, getStaticPropz) ?? { contract: null, bets: [] } - const user = useUser() const inIframe = useIsIframe() if (inIframe) { return @@ -109,9 +85,7 @@ export default function ContractPage(props: { return } - return ( - - ) + return } // requires an admin to resolve a week after market closes @@ -119,12 +93,10 @@ export function needsAdminToResolve(contract: Contract) { return !contract.isResolved && dayjs().diff(contract.closeTime, 'day') > 7 } -export function ContractPageSidebar(props: { - user: User | null | undefined - contract: Contract -}) { - const { contract, user } = props +export function ContractPageSidebar(props: { contract: Contract }) { + const { contract } = props const { creatorId, isResolved, outcomeType } = contract + const user = useUser() const isCreator = user?.id === creatorId const isBinary = outcomeType === 'BINARY' const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC' @@ -173,11 +145,11 @@ export function ContractPageSidebar(props: { export function ContractPageContent( props: Parameters[0] & { contract: Contract - user?: User | null } ) { - const { backToHome, comments, user } = props + const { backToHome } = props const contract = useContractWithPreload(props.contract) ?? props.contract + const user = useUser() usePrefetch(user?.id) useTracking( 'view market', @@ -217,9 +189,8 @@ export function ContractPageContent( contractId: contract.id, }) - const rightSidebar = return ( - + }> {showConfetti && ( )} @@ -228,7 +199,7 @@ export function ContractPageContent( )} @@ -271,22 +242,13 @@ export function ContractPageContent( <>
- +
)} - + {!user ? ( @@ -307,26 +269,28 @@ export function ContractPageContent( ) } -function RecommendedContractsWidget(props: { contract: Contract }) { - const { contract } = props - const user = useUser() - const [recommendations, setRecommendations] = useState([]) - useEffect(() => { - if (user) { - getRecommendedContracts(contract, user.id, 6).then(setRecommendations) +const RecommendedContractsWidget = memo( + function RecommendedContractsWidget(props: { contract: Contract }) { + const { contract } = props + const user = useUser() + const [recommendations, setRecommendations] = useState([]) + useEffect(() => { + if (user) { + getRecommendedContracts(contract, user.id, 6).then(setRecommendations) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [contract.id, user?.id]) + if (recommendations.length === 0) { + return null } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [contract.id, user?.id]) - if (recommendations.length === 0) { - return null + return ( + + + <ContractsGrid + contracts={recommendations} + trackingPostfix=" recommended" + /> + </Col> + ) } - return ( - <Col className="mt-2 gap-2 px-2 sm:px-0"> - <Title className="text-gray-700" text="Recommended" /> - <ContractsGrid - contracts={recommendations} - trackingPostfix=" recommended" - /> - </Col> - ) -} +) diff --git a/web/pages/embed/[username]/[contractSlug].tsx b/web/pages/embed/[username]/[contractSlug].tsx index 62dd1ae1..75a9ad05 100644 --- a/web/pages/embed/[username]/[contractSlug].tsx +++ b/web/pages/embed/[username]/[contractSlug].tsx @@ -34,20 +34,14 @@ export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { username: string; contractSlug: string } }) { - const { username, contractSlug } = props.params + const { contractSlug } = props.params const contract = (await getContractFromSlug(contractSlug)) || null const contractId = contract?.id const bets = contractId ? await listAllBets(contractId) : [] return { - props: { - contract, - username, - slug: contractSlug, - bets, - }, - + props: { contract, bets }, revalidate: 60, // regenerate after a minute } } @@ -58,16 +52,9 @@ export async function getStaticPaths() { export default function ContractEmbedPage(props: { contract: Contract | null - username: string bets: Bet[] - slug: string }) { - props = usePropz(props, getStaticPropz) ?? { - contract: null, - username: '', - bets: [], - slug: '', - } + props = usePropz(props, getStaticPropz) ?? { contract: null, bets: [] } const contract = useContractWithPreload(props.contract) const { bets } = props From 73fad2e34b3000556d80e86da236cf93daad280d Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Wed, 21 Sep 2022 15:31:45 -0400 Subject: [PATCH 02/60] Remove F2P Tournament --- web/pages/tournaments/index.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/pages/tournaments/index.tsx b/web/pages/tournaments/index.tsx index b56e55e6..8378b185 100644 --- a/web/pages/tournaments/index.tsx +++ b/web/pages/tournaments/index.tsx @@ -83,14 +83,14 @@ const tourneys: Tourney[] = [ endTime: toDate('Sep 30, 2022'), groupId: 'fhksfIgqyWf7OxsV9nkM', }, - { - title: 'Manifold F2P Tournament', - blurb: - 'Who can amass the most mana starting from a free-to-play (F2P) account?', - award: 'Poem', - endTime: toDate('Sep 15, 2022'), - groupId: '6rrIja7tVW00lUVwtsYS', - }, + // { + // title: 'Manifold F2P Tournament', + // blurb: + // 'Who can amass the most mana starting from a free-to-play (F2P) account?', + // award: 'Poem', + // endTime: toDate('Sep 15, 2022'), + // groupId: '6rrIja7tVW00lUVwtsYS', + // }, // { // title: 'Cause Exploration Prizes', // blurb: From 24766740c585ab77dbda76f04e83c58f926b5858 Mon Sep 17 00:00:00 2001 From: ingawei <46611122+ingawei@users.noreply.github.com> Date: Wed, 21 Sep 2022 16:48:32 -0500 Subject: [PATCH 03/60] cleaning up search bar for mobile (#916) * cleaning up search bar for mobile --- web/components/contract-search.tsx | 131 +++++++++++++++++++++++------ 1 file changed, 107 insertions(+), 24 deletions(-) diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index 3d25dcdd..7ab28cbb 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -9,7 +9,14 @@ import { } from './contract/contracts-grid' import { ShowTime } from './contract/contract-details' import { Row } from './layout/row' -import { useEffect, useLayoutEffect, useRef, useMemo, ReactNode } from 'react' +import { + useEffect, + useLayoutEffect, + useRef, + useMemo, + ReactNode, + useState, +} from 'react' import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants' import { useFollows } from 'web/hooks/use-follows' import { @@ -32,6 +39,11 @@ import { searchClient, searchIndexName, } from 'web/lib/service/algolia' +import { useIsMobile } from 'web/hooks/use-is-mobile' +import { AdjustmentsIcon } from '@heroicons/react/solid' +import { Button } from './button' +import { Modal } from './layout/modal' +import { Title } from './title' export const SORTS = [ { label: 'Newest', value: 'newest' }, @@ -270,6 +282,8 @@ function ContractSearchControls(props: { } ) + const isMobile = useIsMobile() + const sortKey = `${persistPrefix}-search-sort` const savedSort = safeLocalStorage()?.getItem(sortKey) @@ -415,30 +429,31 @@ function ContractSearchControls(props: { className="input input-bordered w-full" autoFocus={autoFocus} /> - {!query && ( - <select - className="select select-bordered" - value={filter} - onChange={(e) => selectFilter(e.target.value as filter)} - > - <option value="open">Open</option> - <option value="closed">Closed</option> - <option value="resolved">Resolved</option> - <option value="all">All</option> - </select> + {!isMobile && ( + <SearchFilters + filter={filter} + selectFilter={selectFilter} + hideOrderSelector={hideOrderSelector} + selectSort={selectSort} + sort={sort} + className={'flex flex-row gap-2'} + /> )} - {!hideOrderSelector && !query && ( - <select - className="select select-bordered" - value={sort} - onChange={(e) => selectSort(e.target.value as Sort)} - > - {SORTS.map((option) => ( - <option key={option.value} value={option.value}> - {option.label} - </option> - ))} - </select> + {isMobile && ( + <> + <MobileSearchBar + children={ + <SearchFilters + filter={filter} + selectFilter={selectFilter} + hideOrderSelector={hideOrderSelector} + selectSort={selectSort} + sort={sort} + className={'flex flex-col gap-4'} + /> + } + /> + </> )} </Row> @@ -481,3 +496,71 @@ function ContractSearchControls(props: { </Col> ) } + +export function SearchFilters(props: { + filter: string + selectFilter: (newFilter: filter) => void + hideOrderSelector: boolean | undefined + selectSort: (newSort: Sort) => void + sort: string + className?: string +}) { + const { + filter, + selectFilter, + hideOrderSelector, + selectSort, + sort, + className, + } = props + return ( + <div className={className}> + <select + className="select select-bordered" + value={filter} + onChange={(e) => selectFilter(e.target.value as filter)} + > + <option value="open">Open</option> + <option value="closed">Closed</option> + <option value="resolved">Resolved</option> + <option value="all">All</option> + </select> + {!hideOrderSelector && ( + <select + className="select select-bordered" + value={sort} + onChange={(e) => selectSort(e.target.value as Sort)} + > + {SORTS.map((option) => ( + <option key={option.value} value={option.value}> + {option.label} + </option> + ))} + </select> + )} + </div> + ) +} + +export function MobileSearchBar(props: { children: ReactNode }) { + const { children } = props + const [openFilters, setOpenFilters] = useState(false) + return ( + <> + <Button color="gray-white" onClick={() => setOpenFilters(true)}> + <AdjustmentsIcon className="my-auto h-7" /> + </Button> + <Modal + open={openFilters} + setOpen={setOpenFilters} + position="top" + className="rounded-lg bg-white px-4 pb-4" + > + <Col> + <Title text="Filter Markets" /> + {children} + </Col> + </Modal> + </> + ) +} From d922900bda2e7ea804d8a3daa28cc828b15f9278 Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Wed, 21 Sep 2022 18:25:54 -0400 Subject: [PATCH 04/60] Increase tip size to M$10 --- web/components/tipper.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/web/components/tipper.tsx b/web/components/tipper.tsx index 7aef6189..46a988f6 100644 --- a/web/components/tipper.tsx +++ b/web/components/tipper.tsx @@ -16,6 +16,8 @@ import { track } from 'web/lib/service/analytics' import { Row } from './layout/row' import { Tooltip } from './tooltip' +const TIP_SIZE = 10 + export function Tipper(prop: { comment: Comment; tips: CommentTips }) { const { comment, tips } = prop @@ -82,9 +84,12 @@ export function Tipper(prop: { comment: Comment; tips: CommentTips }) { const canUp = me && me.id !== comment.userId && me.balance >= localTip + 5 return ( <Row className="items-center gap-0.5"> - <DownTip onClick={canDown ? () => addTip(-5) : undefined} /> + <DownTip onClick={canDown ? () => addTip(-TIP_SIZE) : undefined} /> <span className="font-bold">{Math.floor(total)}</span> - <UpTip onClick={canUp ? () => addTip(+5) : undefined} value={localTip} /> + <UpTip + onClick={canUp ? () => addTip(+TIP_SIZE) : undefined} + value={localTip} + /> {localTip === 0 ? ( '' ) : ( @@ -107,7 +112,7 @@ function DownTip(props: { onClick?: () => void }) { <Tooltip className="h-6 w-6" placement="bottom" - text={onClick && `-${formatMoney(5)}`} + text={onClick && `-${formatMoney(TIP_SIZE)}`} noTap > <button @@ -128,7 +133,7 @@ function UpTip(props: { onClick?: () => void; value: number }) { <Tooltip className="h-6 w-6" placement="bottom" - text={onClick && `Tip ${formatMoney(5)}`} + text={onClick && `Tip ${formatMoney(TIP_SIZE)}`} noTap > <button From b4a59cfb212dc99d952800e4c18bd2151aa168d5 Mon Sep 17 00:00:00 2001 From: FRC <pico2x@gmail.com> Date: Wed, 21 Sep 2022 23:27:49 +0100 Subject: [PATCH 05/60] Bring back tabs in groups (#919) --- functions/src/utils.ts | 1 - web/components/nav/group-nav-bar.tsx | 94 --------------------- web/components/nav/group-sidebar.tsx | 82 ------------------ web/components/nav/sidebar.tsx | 17 +++- web/components/page.tsx | 14 +++- web/pages/group/[...slugs]/index.tsx | 119 ++++++++------------------- 6 files changed, 60 insertions(+), 267 deletions(-) delete mode 100644 web/components/nav/group-nav-bar.tsx delete mode 100644 web/components/nav/group-sidebar.tsx diff --git a/functions/src/utils.ts b/functions/src/utils.ts index 6bb8349a..eb5fa8f8 100644 --- a/functions/src/utils.ts +++ b/functions/src/utils.ts @@ -1,5 +1,4 @@ import * as admin from 'firebase-admin' -import fetch from 'node-fetch' import { chunk } from 'lodash' import { Contract } from '../../common/contract' diff --git a/web/components/nav/group-nav-bar.tsx b/web/components/nav/group-nav-bar.tsx deleted file mode 100644 index 9ea3f5a4..00000000 --- a/web/components/nav/group-nav-bar.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { ClipboardIcon, HomeIcon } from '@heroicons/react/outline' -import { Item } from './sidebar-item' - -import clsx from 'clsx' -import { trackCallback } from 'web/lib/service/analytics' -import TrophyIcon from 'web/lib/icons/trophy-icon' -import { useUser } from 'web/hooks/use-user' -import NotificationsIcon from '../notifications-icon' -import router from 'next/router' -import { userProfileItem } from './bottom-nav-bar' - -const mobileGroupNavigation = [ - { name: 'Markets', key: 'markets', icon: HomeIcon }, - { name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, - { name: 'About', key: 'about', icon: ClipboardIcon }, -] - -const mobileGeneralNavigation = [ - { - name: 'Notifications', - key: 'notifications', - icon: NotificationsIcon, - href: '/notifications', - }, -] - -export function GroupNavBar(props: { - currentPage: string - onClick: (key: string) => void -}) { - const { currentPage } = props - const user = useUser() - - return ( - <nav className="z-20 flex justify-between border-t-2 bg-white text-xs text-gray-700 lg:hidden"> - {mobileGroupNavigation.map((item) => ( - <NavBarItem - key={item.name} - item={item} - currentPage={currentPage} - onClick={props.onClick} - /> - ))} - - {mobileGeneralNavigation.map((item) => ( - <NavBarItem - key={item.name} - item={item} - currentPage={currentPage} - onClick={() => { - router.push(item.href) - }} - /> - ))} - - {user && ( - <NavBarItem - key={'profile'} - currentPage={currentPage} - onClick={() => { - router.push(`/${user.username}?tab=trades`) - }} - item={userProfileItem(user)} - /> - )} - </nav> - ) -} - -function NavBarItem(props: { - item: Item - currentPage: string - onClick: (key: string) => void -}) { - const { item, currentPage } = props - const track = trackCallback( - `group navbar: ${item.trackingEventName ?? item.name}` - ) - - return ( - <button onClick={() => props.onClick(item.key ?? '#')}> - <a - className={clsx( - 'block w-full py-1 px-3 text-center hover:bg-indigo-200 hover:text-indigo-700', - currentPage === item.key && 'bg-gray-200 text-indigo-700' - )} - onClick={track} - > - {item.icon && <item.icon className="my-1 mx-auto h-6 w-6" />} - {item.name} - </a> - </button> - ) -} diff --git a/web/components/nav/group-sidebar.tsx b/web/components/nav/group-sidebar.tsx deleted file mode 100644 index a68064e0..00000000 --- a/web/components/nav/group-sidebar.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { ClipboardIcon, HomeIcon } from '@heroicons/react/outline' -import clsx from 'clsx' -import { useUser } from 'web/hooks/use-user' -import { ManifoldLogo } from './manifold-logo' -import { ProfileSummary } from './profile-menu' -import React from 'react' -import TrophyIcon from 'web/lib/icons/trophy-icon' -import { SignInButton } from '../sign-in-button' -import NotificationsIcon from '../notifications-icon' -import { SidebarItem } from './sidebar-item' -import { buildArray } from 'common/util/array' -import { User } from 'common/user' -import { Row } from '../layout/row' -import { Spacer } from '../layout/spacer' - -const groupNavigation = [ - { name: 'Markets', key: 'markets', icon: HomeIcon }, - { name: 'About', key: 'about', icon: ClipboardIcon }, - { name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, -] - -const generalNavigation = (user?: User | null) => - buildArray( - user && { - name: 'Notifications', - href: `/notifications`, - key: 'notifications', - icon: NotificationsIcon, - } - ) - -export function GroupSidebar(props: { - groupName: string - className?: string - onClick: (key: string) => void - joinOrAddQuestionsButton: React.ReactNode - currentKey: string -}) { - const { className, groupName, currentKey } = props - - const user = useUser() - - return ( - <nav - aria-label="Group Sidebar" - className={clsx('flex max-h-[100vh] flex-col', className)} - > - <ManifoldLogo className="pt-6" twoLine /> - <Row className="pl-2 text-xl text-indigo-700 sm:mt-3">{groupName}</Row> - - <div className=" min-h-0 shrink flex-col items-stretch gap-1 pt-6 lg:flex "> - {user ? ( - <ProfileSummary user={user} /> - ) : ( - <SignInButton className="mb-4" /> - )} - </div> - - {/* Desktop navigation */} - {groupNavigation.map((item) => ( - <SidebarItem - key={item.key} - item={item} - currentPage={currentKey} - onClick={props.onClick} - /> - ))} - {generalNavigation(user).map((item) => ( - <SidebarItem - key={item.key} - item={item} - currentPage={currentKey} - onClick={props.onClick} - /> - ))} - - <Spacer h={2} /> - - {props.joinOrAddQuestionsButton} - </nav> - ) -} diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx index 45347774..b0a9862b 100644 --- a/web/components/nav/sidebar.tsx +++ b/web/components/nav/sidebar.tsx @@ -26,9 +26,14 @@ import TrophyIcon from 'web/lib/icons/trophy-icon' import { SignInButton } from '../sign-in-button' import { SidebarItem } from './sidebar-item' import { MoreButton } from './more-button' +import { Row } from '../layout/row' +import { Spacer } from '../layout/spacer' -export default function Sidebar(props: { className?: string }) { - const { className } = props +export default function Sidebar(props: { + className?: string + logoSubheading?: string +}) { + const { className, logoSubheading } = props const router = useRouter() const currentPage = router.pathname @@ -51,7 +56,13 @@ export default function Sidebar(props: { className?: string }) { aria-label="Sidebar" className={clsx('flex max-h-[100vh] flex-col', className)} > - <ManifoldLogo className="py-6" twoLine /> + <ManifoldLogo className="pt-6" twoLine /> + {logoSubheading && ( + <Row className="pl-2 text-2xl text-indigo-700 sm:mt-3"> + {logoSubheading} + </Row> + )} + <Spacer h={6} /> {!user && <SignInButton className="mb-4" />} diff --git a/web/components/page.tsx b/web/components/page.tsx index 9b26e9f8..f72db80e 100644 --- a/web/components/page.tsx +++ b/web/components/page.tsx @@ -9,8 +9,15 @@ export function Page(props: { className?: string rightSidebarClassName?: string children?: ReactNode + logoSubheading?: string }) { - const { children, rightSidebar, className, rightSidebarClassName } = props + const { + children, + rightSidebar, + className, + rightSidebarClassName, + logoSubheading, + } = props const bottomBarPadding = 'pb-[58px] lg:pb-0 ' return ( @@ -23,7 +30,10 @@ export function Page(props: { )} > <Toaster /> - <Sidebar className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" /> + <Sidebar + logoSubheading={logoSubheading} + className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" + /> <main className={clsx( 'lg:col-span-8 lg:pt-6', diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index 3adb01c1..cf531db0 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import Link from 'next/link' import { useRouter } from 'next/router' -import { toast, Toaster } from 'react-hot-toast' +import { toast } from 'react-hot-toast' import { Group, GROUP_CHAT_SLUG } from 'common/group' import { Contract, listContractsByGroupSlug } from 'web/lib/firebase/contracts' @@ -48,11 +48,11 @@ import { Spacer } from 'web/components/layout/spacer' import { usePost } from 'web/hooks/use-post' import { useAdmin } from 'web/hooks/use-admin' import { track } from '@amplitude/analytics-browser' -import { GroupNavBar } from 'web/components/nav/group-nav-bar' import { ArrowLeftIcon } from '@heroicons/react/solid' -import { GroupSidebar } from 'web/components/nav/group-sidebar' import { SelectMarketsModal } from 'web/components/contract-select-modal' import { BETTORS } from 'common/user' +import { Page } from 'web/components/page' +import { Tabs } from 'web/components/layout/tabs' export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { slugs: string[] } }) { @@ -140,10 +140,6 @@ export default function GroupPage(props: { const user = useUser() const isAdmin = useAdmin() const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds - // Note: Keep in sync with sidebarPages - const [sidebarIndex, setSidebarIndex] = useState( - ['markets', 'leaderboards', 'about'].indexOf(page ?? 'markets') - ) useSaveReferral(user, { defaultReferrerUsername: creator.username, @@ -157,7 +153,7 @@ export default function GroupPage(props: { const isMember = user && memberIds.includes(user.id) const maxLeaderboardSize = 50 - const leaderboardPage = ( + const leaderboardTab = ( <Col> <div className="mt-4 flex flex-col gap-8 px-4 md:flex-row"> <GroupLeaderboard @@ -176,7 +172,7 @@ export default function GroupPage(props: { </Col> ) - const aboutPage = ( + const aboutTab = ( <Col> {(group.aboutPostId != null || isCreator || isAdmin) && ( <GroupAboutPost @@ -196,16 +192,21 @@ export default function GroupPage(props: { </Col> ) - const questionsPage = ( + const questionsTab = ( <> - {/* align the divs to the right */} - <div className={' flex justify-end px-2 pb-2 sm:hidden'}> - <div> - <JoinOrAddQuestionsButtons - group={group} - user={user} - isMember={!!isMember} - /> + <div className={'flex justify-end '}> + <div + className={ + 'flex items-end justify-self-end px-2 md:absolute md:top-0 md:pb-2' + } + > + <div> + <JoinOrAddQuestionsButtons + group={group} + user={user} + isMember={!!isMember} + /> + </div> </div> </div> <ContractSearch @@ -219,88 +220,37 @@ export default function GroupPage(props: { </> ) - const sidebarPages = [ + const tabs = [ { title: 'Markets', - content: questionsPage, - href: groupPath(group.slug, 'markets'), - key: 'markets', + content: questionsTab, }, { title: 'Leaderboards', - content: leaderboardPage, - href: groupPath(group.slug, 'leaderboards'), - key: 'leaderboards', + content: leaderboardTab, }, { title: 'About', - content: aboutPage, - href: groupPath(group.slug, 'about'), - key: 'about', + content: aboutTab, }, ] - const pageContent = sidebarPages[sidebarIndex].content - const onSidebarClick = (key: string) => { - const index = sidebarPages.findIndex((t) => t.key === key) - setSidebarIndex(index) - // Append the page to the URL, e.g. /group/mexifold/markets - router.replace( - { query: { ...router.query, slugs: [group.slug, key] } }, - undefined, - { shallow: true } - ) - } - - const joinOrAddQuestionsButton = ( - <JoinOrAddQuestionsButtons - group={group} - user={user} - isMember={!!isMember} - /> - ) - return ( - <> - <TopGroupNavBar - group={group} - currentPage={sidebarPages[sidebarIndex].key} - onClick={onSidebarClick} + <Page logoSubheading={group.name}> + <SEO + title={group.name} + description={`Created by ${creator.name}. ${group.about}`} + url={groupPath(group.slug)} /> - <div> - <div - className={ - 'mx-auto w-full pb-[58px] lg:grid lg:grid-cols-12 lg:gap-x-2 lg:pb-0 xl:max-w-7xl xl:gap-x-8' - } - > - <Toaster /> - <GroupSidebar - groupName={group.name} - className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" - onClick={onSidebarClick} - joinOrAddQuestionsButton={joinOrAddQuestionsButton} - currentKey={sidebarPages[sidebarIndex].key} - /> - - <SEO - title={group.name} - description={`Created by ${creator.name}. ${group.about}`} - url={groupPath(group.slug)} - /> - <main className={'px-2 pt-1 lg:col-span-8 lg:pt-6 xl:col-span-8'}> - {pageContent} - </main> - </div> + <TopGroupNavBar group={group} /> + <div className={'relative p-2 pt-0 md:pt-2'}> + <Tabs tabs={tabs} /> </div> - </> + </Page> ) } -export function TopGroupNavBar(props: { - group: Group - currentPage: string - onClick: (key: string) => void -}) { +export function TopGroupNavBar(props: { group: Group }) { return ( <header className="sticky top-0 z-50 w-full border-b border-gray-200 md:hidden lg:col-span-12"> <div className="flex items-center bg-white px-4"> @@ -317,7 +267,6 @@ export function TopGroupNavBar(props: { </h1> </div> </div> - <GroupNavBar currentPage={props.currentPage} onClick={props.onClick} /> </header> ) } @@ -330,7 +279,7 @@ function JoinOrAddQuestionsButtons(props: { }) { const { group, user, isMember } = props return user && isMember ? ( - <Row className={'w-full self-start pt-4'}> + <Row className={'w-full self-start md:mt-2 '}> <AddContractButton group={group} user={user} /> </Row> ) : group.anyoneCanJoin ? ( From b875ac563d08b060fe731ee16f1ac7f17ac15b7d Mon Sep 17 00:00:00 2001 From: Pico2x <pico2x@gmail.com> Date: Wed, 21 Sep 2022 19:14:05 -0400 Subject: [PATCH 06/60] Revert "Bring back tabs in groups (#919)" This reverts commit b4a59cfb212dc99d952800e4c18bd2151aa168d5. --- functions/src/utils.ts | 1 + web/components/nav/group-nav-bar.tsx | 94 +++++++++++++++++++++ web/components/nav/group-sidebar.tsx | 82 ++++++++++++++++++ web/components/nav/sidebar.tsx | 17 +--- web/components/page.tsx | 14 +--- web/pages/group/[...slugs]/index.tsx | 119 +++++++++++++++++++-------- 6 files changed, 267 insertions(+), 60 deletions(-) create mode 100644 web/components/nav/group-nav-bar.tsx create mode 100644 web/components/nav/group-sidebar.tsx diff --git a/functions/src/utils.ts b/functions/src/utils.ts index eb5fa8f8..6bb8349a 100644 --- a/functions/src/utils.ts +++ b/functions/src/utils.ts @@ -1,4 +1,5 @@ import * as admin from 'firebase-admin' +import fetch from 'node-fetch' import { chunk } from 'lodash' import { Contract } from '../../common/contract' diff --git a/web/components/nav/group-nav-bar.tsx b/web/components/nav/group-nav-bar.tsx new file mode 100644 index 00000000..9ea3f5a4 --- /dev/null +++ b/web/components/nav/group-nav-bar.tsx @@ -0,0 +1,94 @@ +import { ClipboardIcon, HomeIcon } from '@heroicons/react/outline' +import { Item } from './sidebar-item' + +import clsx from 'clsx' +import { trackCallback } from 'web/lib/service/analytics' +import TrophyIcon from 'web/lib/icons/trophy-icon' +import { useUser } from 'web/hooks/use-user' +import NotificationsIcon from '../notifications-icon' +import router from 'next/router' +import { userProfileItem } from './bottom-nav-bar' + +const mobileGroupNavigation = [ + { name: 'Markets', key: 'markets', icon: HomeIcon }, + { name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, + { name: 'About', key: 'about', icon: ClipboardIcon }, +] + +const mobileGeneralNavigation = [ + { + name: 'Notifications', + key: 'notifications', + icon: NotificationsIcon, + href: '/notifications', + }, +] + +export function GroupNavBar(props: { + currentPage: string + onClick: (key: string) => void +}) { + const { currentPage } = props + const user = useUser() + + return ( + <nav className="z-20 flex justify-between border-t-2 bg-white text-xs text-gray-700 lg:hidden"> + {mobileGroupNavigation.map((item) => ( + <NavBarItem + key={item.name} + item={item} + currentPage={currentPage} + onClick={props.onClick} + /> + ))} + + {mobileGeneralNavigation.map((item) => ( + <NavBarItem + key={item.name} + item={item} + currentPage={currentPage} + onClick={() => { + router.push(item.href) + }} + /> + ))} + + {user && ( + <NavBarItem + key={'profile'} + currentPage={currentPage} + onClick={() => { + router.push(`/${user.username}?tab=trades`) + }} + item={userProfileItem(user)} + /> + )} + </nav> + ) +} + +function NavBarItem(props: { + item: Item + currentPage: string + onClick: (key: string) => void +}) { + const { item, currentPage } = props + const track = trackCallback( + `group navbar: ${item.trackingEventName ?? item.name}` + ) + + return ( + <button onClick={() => props.onClick(item.key ?? '#')}> + <a + className={clsx( + 'block w-full py-1 px-3 text-center hover:bg-indigo-200 hover:text-indigo-700', + currentPage === item.key && 'bg-gray-200 text-indigo-700' + )} + onClick={track} + > + {item.icon && <item.icon className="my-1 mx-auto h-6 w-6" />} + {item.name} + </a> + </button> + ) +} diff --git a/web/components/nav/group-sidebar.tsx b/web/components/nav/group-sidebar.tsx new file mode 100644 index 00000000..a68064e0 --- /dev/null +++ b/web/components/nav/group-sidebar.tsx @@ -0,0 +1,82 @@ +import { ClipboardIcon, HomeIcon } from '@heroicons/react/outline' +import clsx from 'clsx' +import { useUser } from 'web/hooks/use-user' +import { ManifoldLogo } from './manifold-logo' +import { ProfileSummary } from './profile-menu' +import React from 'react' +import TrophyIcon from 'web/lib/icons/trophy-icon' +import { SignInButton } from '../sign-in-button' +import NotificationsIcon from '../notifications-icon' +import { SidebarItem } from './sidebar-item' +import { buildArray } from 'common/util/array' +import { User } from 'common/user' +import { Row } from '../layout/row' +import { Spacer } from '../layout/spacer' + +const groupNavigation = [ + { name: 'Markets', key: 'markets', icon: HomeIcon }, + { name: 'About', key: 'about', icon: ClipboardIcon }, + { name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, +] + +const generalNavigation = (user?: User | null) => + buildArray( + user && { + name: 'Notifications', + href: `/notifications`, + key: 'notifications', + icon: NotificationsIcon, + } + ) + +export function GroupSidebar(props: { + groupName: string + className?: string + onClick: (key: string) => void + joinOrAddQuestionsButton: React.ReactNode + currentKey: string +}) { + const { className, groupName, currentKey } = props + + const user = useUser() + + return ( + <nav + aria-label="Group Sidebar" + className={clsx('flex max-h-[100vh] flex-col', className)} + > + <ManifoldLogo className="pt-6" twoLine /> + <Row className="pl-2 text-xl text-indigo-700 sm:mt-3">{groupName}</Row> + + <div className=" min-h-0 shrink flex-col items-stretch gap-1 pt-6 lg:flex "> + {user ? ( + <ProfileSummary user={user} /> + ) : ( + <SignInButton className="mb-4" /> + )} + </div> + + {/* Desktop navigation */} + {groupNavigation.map((item) => ( + <SidebarItem + key={item.key} + item={item} + currentPage={currentKey} + onClick={props.onClick} + /> + ))} + {generalNavigation(user).map((item) => ( + <SidebarItem + key={item.key} + item={item} + currentPage={currentKey} + onClick={props.onClick} + /> + ))} + + <Spacer h={2} /> + + {props.joinOrAddQuestionsButton} + </nav> + ) +} diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx index b0a9862b..45347774 100644 --- a/web/components/nav/sidebar.tsx +++ b/web/components/nav/sidebar.tsx @@ -26,14 +26,9 @@ import TrophyIcon from 'web/lib/icons/trophy-icon' import { SignInButton } from '../sign-in-button' import { SidebarItem } from './sidebar-item' import { MoreButton } from './more-button' -import { Row } from '../layout/row' -import { Spacer } from '../layout/spacer' -export default function Sidebar(props: { - className?: string - logoSubheading?: string -}) { - const { className, logoSubheading } = props +export default function Sidebar(props: { className?: string }) { + const { className } = props const router = useRouter() const currentPage = router.pathname @@ -56,13 +51,7 @@ export default function Sidebar(props: { aria-label="Sidebar" className={clsx('flex max-h-[100vh] flex-col', className)} > - <ManifoldLogo className="pt-6" twoLine /> - {logoSubheading && ( - <Row className="pl-2 text-2xl text-indigo-700 sm:mt-3"> - {logoSubheading} - </Row> - )} - <Spacer h={6} /> + <ManifoldLogo className="py-6" twoLine /> {!user && <SignInButton className="mb-4" />} diff --git a/web/components/page.tsx b/web/components/page.tsx index f72db80e..9b26e9f8 100644 --- a/web/components/page.tsx +++ b/web/components/page.tsx @@ -9,15 +9,8 @@ export function Page(props: { className?: string rightSidebarClassName?: string children?: ReactNode - logoSubheading?: string }) { - const { - children, - rightSidebar, - className, - rightSidebarClassName, - logoSubheading, - } = props + const { children, rightSidebar, className, rightSidebarClassName } = props const bottomBarPadding = 'pb-[58px] lg:pb-0 ' return ( @@ -30,10 +23,7 @@ export function Page(props: { )} > <Toaster /> - <Sidebar - logoSubheading={logoSubheading} - className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" - /> + <Sidebar className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" /> <main className={clsx( 'lg:col-span-8 lg:pt-6', diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index cf531db0..3adb01c1 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import Link from 'next/link' import { useRouter } from 'next/router' -import { toast } from 'react-hot-toast' +import { toast, Toaster } from 'react-hot-toast' import { Group, GROUP_CHAT_SLUG } from 'common/group' import { Contract, listContractsByGroupSlug } from 'web/lib/firebase/contracts' @@ -48,11 +48,11 @@ import { Spacer } from 'web/components/layout/spacer' import { usePost } from 'web/hooks/use-post' import { useAdmin } from 'web/hooks/use-admin' import { track } from '@amplitude/analytics-browser' +import { GroupNavBar } from 'web/components/nav/group-nav-bar' import { ArrowLeftIcon } from '@heroicons/react/solid' +import { GroupSidebar } from 'web/components/nav/group-sidebar' import { SelectMarketsModal } from 'web/components/contract-select-modal' import { BETTORS } from 'common/user' -import { Page } from 'web/components/page' -import { Tabs } from 'web/components/layout/tabs' export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { slugs: string[] } }) { @@ -140,6 +140,10 @@ export default function GroupPage(props: { const user = useUser() const isAdmin = useAdmin() const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds + // Note: Keep in sync with sidebarPages + const [sidebarIndex, setSidebarIndex] = useState( + ['markets', 'leaderboards', 'about'].indexOf(page ?? 'markets') + ) useSaveReferral(user, { defaultReferrerUsername: creator.username, @@ -153,7 +157,7 @@ export default function GroupPage(props: { const isMember = user && memberIds.includes(user.id) const maxLeaderboardSize = 50 - const leaderboardTab = ( + const leaderboardPage = ( <Col> <div className="mt-4 flex flex-col gap-8 px-4 md:flex-row"> <GroupLeaderboard @@ -172,7 +176,7 @@ export default function GroupPage(props: { </Col> ) - const aboutTab = ( + const aboutPage = ( <Col> {(group.aboutPostId != null || isCreator || isAdmin) && ( <GroupAboutPost @@ -192,21 +196,16 @@ export default function GroupPage(props: { </Col> ) - const questionsTab = ( + const questionsPage = ( <> - <div className={'flex justify-end '}> - <div - className={ - 'flex items-end justify-self-end px-2 md:absolute md:top-0 md:pb-2' - } - > - <div> - <JoinOrAddQuestionsButtons - group={group} - user={user} - isMember={!!isMember} - /> - </div> + {/* align the divs to the right */} + <div className={' flex justify-end px-2 pb-2 sm:hidden'}> + <div> + <JoinOrAddQuestionsButtons + group={group} + user={user} + isMember={!!isMember} + /> </div> </div> <ContractSearch @@ -220,37 +219,88 @@ export default function GroupPage(props: { </> ) - const tabs = [ + const sidebarPages = [ { title: 'Markets', - content: questionsTab, + content: questionsPage, + href: groupPath(group.slug, 'markets'), + key: 'markets', }, { title: 'Leaderboards', - content: leaderboardTab, + content: leaderboardPage, + href: groupPath(group.slug, 'leaderboards'), + key: 'leaderboards', }, { title: 'About', - content: aboutTab, + content: aboutPage, + href: groupPath(group.slug, 'about'), + key: 'about', }, ] + const pageContent = sidebarPages[sidebarIndex].content + const onSidebarClick = (key: string) => { + const index = sidebarPages.findIndex((t) => t.key === key) + setSidebarIndex(index) + // Append the page to the URL, e.g. /group/mexifold/markets + router.replace( + { query: { ...router.query, slugs: [group.slug, key] } }, + undefined, + { shallow: true } + ) + } + + const joinOrAddQuestionsButton = ( + <JoinOrAddQuestionsButtons + group={group} + user={user} + isMember={!!isMember} + /> + ) + return ( - <Page logoSubheading={group.name}> - <SEO - title={group.name} - description={`Created by ${creator.name}. ${group.about}`} - url={groupPath(group.slug)} + <> + <TopGroupNavBar + group={group} + currentPage={sidebarPages[sidebarIndex].key} + onClick={onSidebarClick} /> - <TopGroupNavBar group={group} /> - <div className={'relative p-2 pt-0 md:pt-2'}> - <Tabs tabs={tabs} /> + <div> + <div + className={ + 'mx-auto w-full pb-[58px] lg:grid lg:grid-cols-12 lg:gap-x-2 lg:pb-0 xl:max-w-7xl xl:gap-x-8' + } + > + <Toaster /> + <GroupSidebar + groupName={group.name} + className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" + onClick={onSidebarClick} + joinOrAddQuestionsButton={joinOrAddQuestionsButton} + currentKey={sidebarPages[sidebarIndex].key} + /> + + <SEO + title={group.name} + description={`Created by ${creator.name}. ${group.about}`} + url={groupPath(group.slug)} + /> + <main className={'px-2 pt-1 lg:col-span-8 lg:pt-6 xl:col-span-8'}> + {pageContent} + </main> + </div> </div> - </Page> + </> ) } -export function TopGroupNavBar(props: { group: Group }) { +export function TopGroupNavBar(props: { + group: Group + currentPage: string + onClick: (key: string) => void +}) { return ( <header className="sticky top-0 z-50 w-full border-b border-gray-200 md:hidden lg:col-span-12"> <div className="flex items-center bg-white px-4"> @@ -267,6 +317,7 @@ export function TopGroupNavBar(props: { group: Group }) { </h1> </div> </div> + <GroupNavBar currentPage={props.currentPage} onClick={props.onClick} /> </header> ) } @@ -279,7 +330,7 @@ function JoinOrAddQuestionsButtons(props: { }) { const { group, user, isMember } = props return user && isMember ? ( - <Row className={'w-full self-start md:mt-2 '}> + <Row className={'w-full self-start pt-4'}> <AddContractButton group={group} user={user} /> </Row> ) : group.anyoneCanJoin ? ( From 7988fdde60191ae65695081ec92c8bde56ab79e7 Mon Sep 17 00:00:00 2001 From: ingawei <46611122+ingawei@users.noreply.github.com> Date: Wed, 21 Sep 2022 18:49:20 -0500 Subject: [PATCH 07/60] simplify binary graphs (#921) --- web/components/contract/contract-prob-graph.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/components/contract/contract-prob-graph.tsx b/web/components/contract/contract-prob-graph.tsx index aad44b82..60ef85b5 100644 --- a/web/components/contract/contract-prob-graph.tsx +++ b/web/components/contract/contract-prob-graph.tsx @@ -47,14 +47,14 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: { times.push(latestTime.valueOf()) probs.push(probs[probs.length - 1]) - const quartiles = [0, 25, 50, 75, 100] + const { width } = useWindowSize() + + const quartiles = !width || width < 800 ? [0, 50, 100] : [0, 25, 50, 75, 100] const yTickValues = isBinary ? quartiles : quartiles.map((x) => x / 100).map(f) - const { width } = useWindowSize() - const numXTickValues = !width || width < 800 ? 2 : 5 const startDate = dayjs(times[0]) const endDate = startDate.add(1, 'hour').isAfter(latestTime) @@ -104,7 +104,7 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: { return ( <div className="w-full overflow-visible" - style={{ height: height ?? (!width || width >= 800 ? 350 : 250) }} + style={{ height: height ?? (!width || width >= 800 ? 250 : 150) }} > <ResponsiveLine data={data} @@ -144,7 +144,7 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: { pointBorderWidth={1} pointBorderColor="#fff" enableSlices="x" - enableGridX={!!width && width >= 800} + enableGridX={false} enableArea areaBaselineValue={isBinary || isLogScale ? 0 : contract.min} margin={{ top: 20, right: 20, bottom: 25, left: 40 }} From e9ab234d610a41fd1dcad807bd94263e76fcd012 Mon Sep 17 00:00:00 2001 From: Sinclair Chen <abc.sinclair@gmail.com> Date: Wed, 21 Sep 2022 17:49:32 -0700 Subject: [PATCH 08/60] copy: manifold dollars -> mana --- docs/docs/faq.md | 6 +----- web/components/add-funds-button.tsx | 4 ++-- web/pages/add-funds.tsx | 10 +++++----- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/docs/docs/faq.md b/docs/docs/faq.md index 01c4dc36..5c369e39 100644 --- a/docs/docs/faq.md +++ b/docs/docs/faq.md @@ -4,11 +4,7 @@ ### Do I have to pay real money in order to participate? -Nope! Each account starts with a free M$1000. If you invest it wisely, you can increase your total without ever needing to put any real money into the site. - -### What is the name for the currency Manifold uses, represented by M$? - -Manifold Dollars, or mana for short. +Nope! Each account starts with a free 1000 mana (or M$1000 for short). If you invest it wisely, you can increase your total without ever needing to put any real money into the site. ### Can M$ be sold for real money? diff --git a/web/components/add-funds-button.tsx b/web/components/add-funds-button.tsx index 90b24b2c..b610bfee 100644 --- a/web/components/add-funds-button.tsx +++ b/web/components/add-funds-button.tsx @@ -30,10 +30,10 @@ export function AddFundsButton(props: { className?: string }) { <div className="modal"> <div className="modal-box"> - <div className="mb-6 text-xl">Get Manifold Dollars</div> + <div className="mb-6 text-xl">Get Mana</div> <div className="mb-6 text-gray-500"> - Use Manifold Dollars to trade in your favorite markets. <br /> (Not + Buy mana (M$) to trade in your favorite markets. <br /> (Not redeemable for cash.) </div> diff --git a/web/pages/add-funds.tsx b/web/pages/add-funds.tsx index ed25a21a..602de276 100644 --- a/web/pages/add-funds.tsx +++ b/web/pages/add-funds.tsx @@ -24,14 +24,14 @@ export default function AddFundsPage() { return ( <Page> <SEO - title="Get Manifold Dollars" - description="Get Manifold Dollars" + title="Get Mana" + description="Buy mana to trade in your favorite markets on Manifold" url="/add-funds" /> <Col className="items-center"> <Col className="h-full rounded bg-white p-4 py-8 sm:p-8 sm:shadow-md"> - <Title className="!mt-0" text="Get Manifold Dollars" /> + <Title className="!mt-0" text="Get Mana" /> <img className="mb-6 block -scale-x-100 self-center" src="/stylized-crane-black.png" @@ -40,8 +40,8 @@ export default function AddFundsPage() { /> <div className="mb-6 text-gray-500"> - Purchase Manifold Dollars to trade in your favorite markets. <br />{' '} - (Not redeemable for cash.) + Buy mana (M$) to trade in your favorite markets. <br /> (Not + redeemable for cash.) </div> <div className="mb-2 text-sm text-gray-500">Amount</div> From 9ff2b6274017b7a5db4a256b85f31d54cd6e7496 Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Wed, 21 Sep 2022 23:10:22 -0400 Subject: [PATCH 09/60] Remove console log --- web/components/onboarding/welcome.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/components/onboarding/welcome.tsx b/web/components/onboarding/welcome.tsx index b18ef83f..eb51f2de 100644 --- a/web/components/onboarding/welcome.tsx +++ b/web/components/onboarding/welcome.tsx @@ -99,8 +99,6 @@ const useIsTwitch = (user: User | null | undefined) => { const isTwitch = router.pathname === '/twitch' useEffect(() => { - console.log('twich?', isTwitch) - if (isTwitch && user?.shouldShowWelcome) { updateUser(user.id, { ['shouldShowWelcome']: false }) } From c15285aa6412d68e66520fdc2aa792e001a0b04d Mon Sep 17 00:00:00 2001 From: mantikoros <sgrugett@gmail.com> Date: Thu, 22 Sep 2022 00:20:02 -0400 Subject: [PATCH 10/60] pare down sorts; only show high/low prob on groups --- web/components/contract-search.tsx | 22 +++++++++++++++++----- web/pages/group/[...slugs]/index.tsx | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index 7ab28cbb..4b14d4a7 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -49,17 +49,15 @@ export const SORTS = [ { label: 'Newest', value: 'newest' }, { label: 'Trending', value: 'score' }, { label: `Most traded`, value: 'most-traded' }, - { label: '24h volume', value: '24-hour-vol' }, - { label: '24h change', value: 'prob-change-day' }, { label: 'Last updated', value: 'last-updated' }, - { label: 'Subsidy', value: 'liquidity' }, - { label: 'Close date', value: 'close-date' }, + { label: 'Closing soon', value: 'close-date' }, { label: 'Resolve date', value: 'resolve-date' }, { label: 'Highest %', value: 'prob-descending' }, { label: 'Lowest %', value: 'prob-ascending' }, ] as const export type Sort = typeof SORTS[number]['value'] +export const PROB_SORTS = ['prob-descending', 'prob-ascending'] type filter = 'personal' | 'open' | 'closed' | 'resolved' | 'all' @@ -95,6 +93,7 @@ export function ContractSearch(props: { persistPrefix?: string useQueryUrlParam?: boolean isWholePage?: boolean + includeProbSorts?: boolean noControls?: boolean maxResults?: number renderContracts?: ( @@ -116,6 +115,7 @@ export function ContractSearch(props: { headerClassName, persistPrefix, useQueryUrlParam, + includeProbSorts, isWholePage, noControls, maxResults, @@ -221,6 +221,7 @@ export function ContractSearch(props: { persistPrefix={persistPrefix} hideOrderSelector={hideOrderSelector} useQueryUrlParam={useQueryUrlParam} + includeProbSorts={includeProbSorts} user={user} onSearchParametersChanged={onSearchParametersChanged} noControls={noControls} @@ -250,6 +251,7 @@ function ContractSearchControls(props: { additionalFilter?: AdditionalFilter persistPrefix?: string hideOrderSelector?: boolean + includeProbSorts?: boolean onSearchParametersChanged: (params: SearchParameters) => void useQueryUrlParam?: boolean user?: User | null @@ -269,6 +271,7 @@ function ContractSearchControls(props: { user, noControls, autoFocus, + includeProbSorts, } = props const router = useRouter() @@ -437,6 +440,7 @@ function ContractSearchControls(props: { selectSort={selectSort} sort={sort} className={'flex flex-row gap-2'} + includeProbSorts={includeProbSorts} /> )} {isMobile && ( @@ -450,6 +454,7 @@ function ContractSearchControls(props: { selectSort={selectSort} sort={sort} className={'flex flex-col gap-4'} + includeProbSorts={includeProbSorts} /> } /> @@ -504,6 +509,7 @@ export function SearchFilters(props: { selectSort: (newSort: Sort) => void sort: string className?: string + includeProbSorts?: boolean }) { const { filter, @@ -512,7 +518,13 @@ export function SearchFilters(props: { selectSort, sort, className, + includeProbSorts, } = props + + const sorts = includeProbSorts + ? SORTS + : SORTS.filter((sort) => !PROB_SORTS.includes(sort.value)) + return ( <div className={className}> <select @@ -531,7 +543,7 @@ export function SearchFilters(props: { value={sort} onChange={(e) => selectSort(e.target.value as Sort)} > - {SORTS.map((option) => ( + {sorts.map((option) => ( <option key={option.value} value={option.value}> {option.label} </option> diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index 3adb01c1..a486e132 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -215,6 +215,7 @@ export default function GroupPage(props: { defaultFilter={suggestedFilter} additionalFilter={{ groupSlug: group.slug }} persistPrefix={`group-${group.slug}`} + includeProbSorts /> </> ) From 4412d0195cbf9b91d9fab20f54caae6477a3c03a Mon Sep 17 00:00:00 2001 From: Sinclair Chen <abc.sinclair@gmail.com> Date: Thu, 22 Sep 2022 08:53:55 -0700 Subject: [PATCH 11/60] Add tooltips to market header icons (#924) --- .../contract/extra-contract-actions-row.tsx | 42 +++---- .../contract/like-market-button.tsx | 66 +++++----- web/components/follow-market-button.tsx | 118 ++++++++++-------- 3 files changed, 119 insertions(+), 107 deletions(-) diff --git a/web/components/contract/extra-contract-actions-row.tsx b/web/components/contract/extra-contract-actions-row.tsx index af5db9c3..8f4b5579 100644 --- a/web/components/contract/extra-contract-actions-row.tsx +++ b/web/components/contract/extra-contract-actions-row.tsx @@ -1,6 +1,4 @@ -import clsx from 'clsx' import { ShareIcon } from '@heroicons/react/outline' - import { Row } from '../layout/row' import { Contract } from 'web/lib/firebase/contracts' import React, { useState } from 'react' @@ -10,7 +8,7 @@ import { ShareModal } from './share-modal' import { FollowMarketButton } from 'web/components/follow-market-button' import { LikeMarketButton } from 'web/components/contract/like-market-button' import { ContractInfoDialog } from 'web/components/contract/contract-info-dialog' -import { Col } from 'web/components/layout/col' +import { Tooltip } from '../tooltip' export function ExtraContractActionsRow(props: { contract: Contract }) { const { contract } = props @@ -23,27 +21,23 @@ export function ExtraContractActionsRow(props: { contract: Contract }) { {user?.id !== contract.creatorId && ( <LikeMarketButton contract={contract} user={user} /> )} - <Button - size="sm" - color="gray-white" - className={'flex'} - onClick={() => { - setShareOpen(true) - }} - > - <Row> - <ShareIcon className={clsx('h-5 w-5')} aria-hidden="true" /> - </Row> - <ShareModal - isOpen={isShareOpen} - setOpen={setShareOpen} - contract={contract} - user={user} - /> - </Button> - <Col className={'justify-center'}> - <ContractInfoDialog contract={contract} /> - </Col> + <Tooltip text="Share" placement="bottom" noTap noFade> + <Button + size="sm" + color="gray-white" + className={'flex'} + onClick={() => setShareOpen(true)} + > + <ShareIcon className="h-5 w-5" aria-hidden /> + <ShareModal + isOpen={isShareOpen} + setOpen={setShareOpen} + contract={contract} + user={user} + /> + </Button> + </Tooltip> + <ContractInfoDialog contract={contract} /> </Row> ) } diff --git a/web/components/contract/like-market-button.tsx b/web/components/contract/like-market-button.tsx index 01dce32f..7e0c765a 100644 --- a/web/components/contract/like-market-button.tsx +++ b/web/components/contract/like-market-button.tsx @@ -13,6 +13,7 @@ import { Col } from 'web/components/layout/col' import { firebaseLogin } from 'web/lib/firebase/users' import { useMarketTipTxns } from 'web/hooks/use-tip-txns' import { sum } from 'lodash' +import { Tooltip } from '../tooltip' export function LikeMarketButton(props: { contract: Contract @@ -37,37 +38,44 @@ export function LikeMarketButton(props: { } return ( - <Button - size={'sm'} - className={'max-w-xs self-center'} - color={'gray-white'} - onClick={onLike} + <Tooltip + text={`Tip ${formatMoney(LIKE_TIP_AMOUNT)}`} + placement="bottom" + noTap + noFade > - <Col className={'relative items-center sm:flex-row'}> - <HeartIcon - className={clsx( - 'h-5 w-5 sm:h-6 sm:w-6', - totalTipped > 0 ? 'mr-2' : '', - user && - (userLikedContractIds?.includes(contract.id) || - (!likes && contract.likedByUserIds?.includes(user.id))) - ? 'fill-red-500 text-red-500' - : '' - )} - /> - {totalTipped > 0 && ( - <div + <Button + size={'sm'} + className={'max-w-xs self-center'} + color={'gray-white'} + onClick={onLike} + > + <Col className={'relative items-center sm:flex-row'}> + <HeartIcon className={clsx( - 'bg-greyscale-6 absolute ml-3.5 mt-2 h-4 w-4 rounded-full align-middle text-white sm:mt-3 sm:h-5 sm:w-5 sm:px-1', - totalTipped > 99 - ? 'text-[0.4rem] sm:text-[0.5rem]' - : 'sm:text-2xs text-[0.5rem]' + 'h-5 w-5 sm:h-6 sm:w-6', + totalTipped > 0 ? 'mr-2' : '', + user && + (userLikedContractIds?.includes(contract.id) || + (!likes && contract.likedByUserIds?.includes(user.id))) + ? 'fill-red-500 text-red-500' + : '' )} - > - {totalTipped} - </div> - )} - </Col> - </Button> + /> + {totalTipped > 0 && ( + <div + className={clsx( + 'bg-greyscale-6 absolute ml-3.5 mt-2 h-4 w-4 rounded-full align-middle text-white sm:mt-3 sm:h-5 sm:w-5 sm:px-1', + totalTipped > 99 + ? 'text-[0.4rem] sm:text-[0.5rem]' + : 'sm:text-2xs text-[0.5rem]' + )} + > + {totalTipped} + </div> + )} + </Col> + </Button> + </Tooltip> ) } diff --git a/web/components/follow-market-button.tsx b/web/components/follow-market-button.tsx index 0e65165b..319d4af6 100644 --- a/web/components/follow-market-button.tsx +++ b/web/components/follow-market-button.tsx @@ -14,6 +14,7 @@ import { track } from 'web/lib/service/analytics' import { WatchMarketModal } from 'web/components/contract/watch-market-modal' import { useState } from 'react' import { Col } from 'web/components/layout/col' +import { Tooltip } from './tooltip' export const FollowMarketButton = (props: { contract: Contract @@ -23,61 +24,70 @@ export const FollowMarketButton = (props: { const followers = useContractFollows(contract.id) const [open, setOpen] = useState(false) + const watching = followers?.includes(user?.id ?? 'nope') + return ( - <Button - size={'sm'} - color={'gray-white'} - onClick={async () => { - if (!user) return firebaseLogin() - if (followers?.includes(user.id)) { - await unFollowContract(contract.id, user.id) - toast("You'll no longer receive notifications from this market", { - icon: <CheckIcon className={'text-primary h-5 w-5'} />, - }) - track('Unwatch Market', { - slug: contract.slug, - }) - } else { - await followContract(contract.id, user.id) - toast("You'll now receive notifications from this market!", { - icon: <CheckIcon className={'text-primary h-5 w-5'} />, - }) - track('Watch Market', { - slug: contract.slug, - }) - } - if (!user.hasSeenContractFollowModal) { - await updateUser(user.id, { - hasSeenContractFollowModal: true, - }) - setOpen(true) - } - }} + <Tooltip + text={watching ? 'Unfollow' : 'Follow'} + placement="bottom" + noTap + noFade > - {followers?.includes(user?.id ?? 'nope') ? ( - <Col className={'items-center gap-x-2 sm:flex-row'}> - <EyeOffIcon - className={clsx('h-5 w-5 sm:h-6 sm:w-6')} - aria-hidden="true" - /> - {/* Unwatch */} - </Col> - ) : ( - <Col className={'items-center gap-x-2 sm:flex-row'}> - <EyeIcon - className={clsx('h-5 w-5 sm:h-6 sm:w-6')} - aria-hidden="true" - /> - {/* Watch */} - </Col> - )} - <WatchMarketModal - open={open} - setOpen={setOpen} - title={`You ${ - followers?.includes(user?.id ?? 'nope') ? 'watched' : 'unwatched' - } a question!`} - /> - </Button> + <Button + size={'sm'} + color={'gray-white'} + onClick={async () => { + if (!user) return firebaseLogin() + if (followers?.includes(user.id)) { + await unFollowContract(contract.id, user.id) + toast("You'll no longer receive notifications from this market", { + icon: <CheckIcon className={'text-primary h-5 w-5'} />, + }) + track('Unwatch Market', { + slug: contract.slug, + }) + } else { + await followContract(contract.id, user.id) + toast("You'll now receive notifications from this market!", { + icon: <CheckIcon className={'text-primary h-5 w-5'} />, + }) + track('Watch Market', { + slug: contract.slug, + }) + } + if (!user.hasSeenContractFollowModal) { + await updateUser(user.id, { + hasSeenContractFollowModal: true, + }) + setOpen(true) + } + }} + > + {watching ? ( + <Col className={'items-center gap-x-2 sm:flex-row'}> + <EyeOffIcon + className={clsx('h-5 w-5 sm:h-6 sm:w-6')} + aria-hidden="true" + /> + {/* Unwatch */} + </Col> + ) : ( + <Col className={'items-center gap-x-2 sm:flex-row'}> + <EyeIcon + className={clsx('h-5 w-5 sm:h-6 sm:w-6')} + aria-hidden="true" + /> + {/* Watch */} + </Col> + )} + <WatchMarketModal + open={open} + setOpen={setOpen} + title={`You ${ + followers?.includes(user?.id ?? 'nope') ? 'watched' : 'unwatched' + } a question!`} + /> + </Button> + </Tooltip> ) } From a5e293c010f32f54b923f01b47265149d1cc3310 Mon Sep 17 00:00:00 2001 From: FRC <pico2x@gmail.com> Date: Thu, 22 Sep 2022 12:12:53 -0400 Subject: [PATCH 12/60] Bring back tabs in groups (#923) --- web/components/contract/contract-tabs.tsx | 1 + web/components/following-button.tsx | 1 + web/components/layout/tabs.tsx | 2 +- web/components/nav/group-nav-bar.tsx | 94 ----------------- web/components/nav/group-sidebar.tsx | 82 --------------- web/components/nav/sidebar.tsx | 17 ++- web/components/page.tsx | 14 ++- web/components/referrals-button.tsx | 1 + web/pages/challenges/index.tsx | 2 +- web/pages/group/[...slugs]/index.tsx | 123 +++++++--------------- web/pages/groups.tsx | 1 + web/pages/leaderboards.tsx | 1 + web/pages/stats.tsx | 8 ++ 13 files changed, 78 insertions(+), 269 deletions(-) delete mode 100644 web/components/nav/group-nav-bar.tsx delete mode 100644 web/components/nav/group-sidebar.tsx diff --git a/web/components/contract/contract-tabs.tsx b/web/components/contract/contract-tabs.tsx index 008eb584..17471796 100644 --- a/web/components/contract/contract-tabs.tsx +++ b/web/components/contract/contract-tabs.tsx @@ -49,6 +49,7 @@ export function ContractTabs(props: { contract: Contract; bets: Bet[] }) { return ( <Tabs + className="mb-4" currentPageForAnalytics={'contract'} tabs={[ { diff --git a/web/components/following-button.tsx b/web/components/following-button.tsx index fdf739a1..135f43a8 100644 --- a/web/components/following-button.tsx +++ b/web/components/following-button.tsx @@ -115,6 +115,7 @@ function FollowsDialog(props: { <div className="p-2 pb-1 text-xl">{user.name}</div> <div className="p-2 pt-0 text-sm text-gray-500">@{user.username}</div> <Tabs + className="mb-4" tabs={[ { title: 'Following', diff --git a/web/components/layout/tabs.tsx b/web/components/layout/tabs.tsx index 3d72b13c..45e7e297 100644 --- a/web/components/layout/tabs.tsx +++ b/web/components/layout/tabs.tsx @@ -31,7 +31,7 @@ export function ControlledTabs(props: TabProps & { activeIndex: number }) { return ( <> <nav - className={clsx('mb-4 space-x-8 border-b border-gray-200', className)} + className={clsx(' space-x-8 border-b border-gray-200', className)} aria-label="Tabs" > {tabs.map((tab, i) => ( diff --git a/web/components/nav/group-nav-bar.tsx b/web/components/nav/group-nav-bar.tsx deleted file mode 100644 index 9ea3f5a4..00000000 --- a/web/components/nav/group-nav-bar.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { ClipboardIcon, HomeIcon } from '@heroicons/react/outline' -import { Item } from './sidebar-item' - -import clsx from 'clsx' -import { trackCallback } from 'web/lib/service/analytics' -import TrophyIcon from 'web/lib/icons/trophy-icon' -import { useUser } from 'web/hooks/use-user' -import NotificationsIcon from '../notifications-icon' -import router from 'next/router' -import { userProfileItem } from './bottom-nav-bar' - -const mobileGroupNavigation = [ - { name: 'Markets', key: 'markets', icon: HomeIcon }, - { name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, - { name: 'About', key: 'about', icon: ClipboardIcon }, -] - -const mobileGeneralNavigation = [ - { - name: 'Notifications', - key: 'notifications', - icon: NotificationsIcon, - href: '/notifications', - }, -] - -export function GroupNavBar(props: { - currentPage: string - onClick: (key: string) => void -}) { - const { currentPage } = props - const user = useUser() - - return ( - <nav className="z-20 flex justify-between border-t-2 bg-white text-xs text-gray-700 lg:hidden"> - {mobileGroupNavigation.map((item) => ( - <NavBarItem - key={item.name} - item={item} - currentPage={currentPage} - onClick={props.onClick} - /> - ))} - - {mobileGeneralNavigation.map((item) => ( - <NavBarItem - key={item.name} - item={item} - currentPage={currentPage} - onClick={() => { - router.push(item.href) - }} - /> - ))} - - {user && ( - <NavBarItem - key={'profile'} - currentPage={currentPage} - onClick={() => { - router.push(`/${user.username}?tab=trades`) - }} - item={userProfileItem(user)} - /> - )} - </nav> - ) -} - -function NavBarItem(props: { - item: Item - currentPage: string - onClick: (key: string) => void -}) { - const { item, currentPage } = props - const track = trackCallback( - `group navbar: ${item.trackingEventName ?? item.name}` - ) - - return ( - <button onClick={() => props.onClick(item.key ?? '#')}> - <a - className={clsx( - 'block w-full py-1 px-3 text-center hover:bg-indigo-200 hover:text-indigo-700', - currentPage === item.key && 'bg-gray-200 text-indigo-700' - )} - onClick={track} - > - {item.icon && <item.icon className="my-1 mx-auto h-6 w-6" />} - {item.name} - </a> - </button> - ) -} diff --git a/web/components/nav/group-sidebar.tsx b/web/components/nav/group-sidebar.tsx deleted file mode 100644 index a68064e0..00000000 --- a/web/components/nav/group-sidebar.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { ClipboardIcon, HomeIcon } from '@heroicons/react/outline' -import clsx from 'clsx' -import { useUser } from 'web/hooks/use-user' -import { ManifoldLogo } from './manifold-logo' -import { ProfileSummary } from './profile-menu' -import React from 'react' -import TrophyIcon from 'web/lib/icons/trophy-icon' -import { SignInButton } from '../sign-in-button' -import NotificationsIcon from '../notifications-icon' -import { SidebarItem } from './sidebar-item' -import { buildArray } from 'common/util/array' -import { User } from 'common/user' -import { Row } from '../layout/row' -import { Spacer } from '../layout/spacer' - -const groupNavigation = [ - { name: 'Markets', key: 'markets', icon: HomeIcon }, - { name: 'About', key: 'about', icon: ClipboardIcon }, - { name: 'Leaderboard', key: 'leaderboards', icon: TrophyIcon }, -] - -const generalNavigation = (user?: User | null) => - buildArray( - user && { - name: 'Notifications', - href: `/notifications`, - key: 'notifications', - icon: NotificationsIcon, - } - ) - -export function GroupSidebar(props: { - groupName: string - className?: string - onClick: (key: string) => void - joinOrAddQuestionsButton: React.ReactNode - currentKey: string -}) { - const { className, groupName, currentKey } = props - - const user = useUser() - - return ( - <nav - aria-label="Group Sidebar" - className={clsx('flex max-h-[100vh] flex-col', className)} - > - <ManifoldLogo className="pt-6" twoLine /> - <Row className="pl-2 text-xl text-indigo-700 sm:mt-3">{groupName}</Row> - - <div className=" min-h-0 shrink flex-col items-stretch gap-1 pt-6 lg:flex "> - {user ? ( - <ProfileSummary user={user} /> - ) : ( - <SignInButton className="mb-4" /> - )} - </div> - - {/* Desktop navigation */} - {groupNavigation.map((item) => ( - <SidebarItem - key={item.key} - item={item} - currentPage={currentKey} - onClick={props.onClick} - /> - ))} - {generalNavigation(user).map((item) => ( - <SidebarItem - key={item.key} - item={item} - currentPage={currentKey} - onClick={props.onClick} - /> - ))} - - <Spacer h={2} /> - - {props.joinOrAddQuestionsButton} - </nav> - ) -} diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx index 45347774..b0a9862b 100644 --- a/web/components/nav/sidebar.tsx +++ b/web/components/nav/sidebar.tsx @@ -26,9 +26,14 @@ import TrophyIcon from 'web/lib/icons/trophy-icon' import { SignInButton } from '../sign-in-button' import { SidebarItem } from './sidebar-item' import { MoreButton } from './more-button' +import { Row } from '../layout/row' +import { Spacer } from '../layout/spacer' -export default function Sidebar(props: { className?: string }) { - const { className } = props +export default function Sidebar(props: { + className?: string + logoSubheading?: string +}) { + const { className, logoSubheading } = props const router = useRouter() const currentPage = router.pathname @@ -51,7 +56,13 @@ export default function Sidebar(props: { className?: string }) { aria-label="Sidebar" className={clsx('flex max-h-[100vh] flex-col', className)} > - <ManifoldLogo className="py-6" twoLine /> + <ManifoldLogo className="pt-6" twoLine /> + {logoSubheading && ( + <Row className="pl-2 text-2xl text-indigo-700 sm:mt-3"> + {logoSubheading} + </Row> + )} + <Spacer h={6} /> {!user && <SignInButton className="mb-4" />} diff --git a/web/components/page.tsx b/web/components/page.tsx index 9b26e9f8..f72db80e 100644 --- a/web/components/page.tsx +++ b/web/components/page.tsx @@ -9,8 +9,15 @@ export function Page(props: { className?: string rightSidebarClassName?: string children?: ReactNode + logoSubheading?: string }) { - const { children, rightSidebar, className, rightSidebarClassName } = props + const { + children, + rightSidebar, + className, + rightSidebarClassName, + logoSubheading, + } = props const bottomBarPadding = 'pb-[58px] lg:pb-0 ' return ( @@ -23,7 +30,10 @@ export function Page(props: { )} > <Toaster /> - <Sidebar className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" /> + <Sidebar + logoSubheading={logoSubheading} + className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" + /> <main className={clsx( 'lg:col-span-8 lg:pt-6', diff --git a/web/components/referrals-button.tsx b/web/components/referrals-button.tsx index 4b4f7095..b164e10c 100644 --- a/web/components/referrals-button.tsx +++ b/web/components/referrals-button.tsx @@ -64,6 +64,7 @@ function ReferralsDialog(props: { <div className="p-2 pb-1 text-xl">{user.name}</div> <div className="p-2 pt-0 text-sm text-gray-500">@{user.username}</div> <Tabs + className="mb-4" tabs={[ { title: 'Referrals', diff --git a/web/pages/challenges/index.tsx b/web/pages/challenges/index.tsx index 11d0f9ab..16999aaa 100644 --- a/web/pages/challenges/index.tsx +++ b/web/pages/challenges/index.tsx @@ -92,7 +92,7 @@ export default function ChallengesListPage() { tap the button above to create a new market & challenge in one. </p> - <Tabs tabs={[...userTab, ...publicTab]} /> + <Tabs className="mb-4" tabs={[...userTab, ...publicTab]} /> </Col> </Page> ) diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index a486e132..779677c4 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import Link from 'next/link' import { useRouter } from 'next/router' -import { toast, Toaster } from 'react-hot-toast' +import { toast } from 'react-hot-toast' import { Group, GROUP_CHAT_SLUG } from 'common/group' import { Contract, listContractsByGroupSlug } from 'web/lib/firebase/contracts' @@ -48,11 +48,11 @@ import { Spacer } from 'web/components/layout/spacer' import { usePost } from 'web/hooks/use-post' import { useAdmin } from 'web/hooks/use-admin' import { track } from '@amplitude/analytics-browser' -import { GroupNavBar } from 'web/components/nav/group-nav-bar' import { ArrowLeftIcon } from '@heroicons/react/solid' -import { GroupSidebar } from 'web/components/nav/group-sidebar' import { SelectMarketsModal } from 'web/components/contract-select-modal' import { BETTORS } from 'common/user' +import { Page } from 'web/components/page' +import { Tabs } from 'web/components/layout/tabs' export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { slugs: string[] } }) { @@ -140,10 +140,6 @@ export default function GroupPage(props: { const user = useUser() const isAdmin = useAdmin() const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds - // Note: Keep in sync with sidebarPages - const [sidebarIndex, setSidebarIndex] = useState( - ['markets', 'leaderboards', 'about'].indexOf(page ?? 'markets') - ) useSaveReferral(user, { defaultReferrerUsername: creator.username, @@ -157,7 +153,7 @@ export default function GroupPage(props: { const isMember = user && memberIds.includes(user.id) const maxLeaderboardSize = 50 - const leaderboardPage = ( + const leaderboardTab = ( <Col> <div className="mt-4 flex flex-col gap-8 px-4 md:flex-row"> <GroupLeaderboard @@ -176,7 +172,7 @@ export default function GroupPage(props: { </Col> ) - const aboutPage = ( + const aboutTab = ( <Col> {(group.aboutPostId != null || isCreator || isAdmin) && ( <GroupAboutPost @@ -196,16 +192,21 @@ export default function GroupPage(props: { </Col> ) - const questionsPage = ( + const questionsTab = ( <> - {/* align the divs to the right */} - <div className={' flex justify-end px-2 pb-2 sm:hidden'}> - <div> - <JoinOrAddQuestionsButtons - group={group} - user={user} - isMember={!!isMember} - /> + <div className={'flex justify-end '}> + <div + className={ + 'flex items-end justify-self-end px-2 md:absolute md:top-0 md:pb-2' + } + > + <div> + <JoinOrAddQuestionsButtons + group={group} + user={user} + isMember={!!isMember} + /> + </div> </div> </div> <ContractSearch @@ -220,88 +221,37 @@ export default function GroupPage(props: { </> ) - const sidebarPages = [ + const tabs = [ { title: 'Markets', - content: questionsPage, - href: groupPath(group.slug, 'markets'), - key: 'markets', + content: questionsTab, }, { title: 'Leaderboards', - content: leaderboardPage, - href: groupPath(group.slug, 'leaderboards'), - key: 'leaderboards', + content: leaderboardTab, }, { title: 'About', - content: aboutPage, - href: groupPath(group.slug, 'about'), - key: 'about', + content: aboutTab, }, ] - const pageContent = sidebarPages[sidebarIndex].content - const onSidebarClick = (key: string) => { - const index = sidebarPages.findIndex((t) => t.key === key) - setSidebarIndex(index) - // Append the page to the URL, e.g. /group/mexifold/markets - router.replace( - { query: { ...router.query, slugs: [group.slug, key] } }, - undefined, - { shallow: true } - ) - } - - const joinOrAddQuestionsButton = ( - <JoinOrAddQuestionsButtons - group={group} - user={user} - isMember={!!isMember} - /> - ) - return ( - <> - <TopGroupNavBar - group={group} - currentPage={sidebarPages[sidebarIndex].key} - onClick={onSidebarClick} + <Page logoSubheading={group.name}> + <SEO + title={group.name} + description={`Created by ${creator.name}. ${group.about}`} + url={groupPath(group.slug)} /> - <div> - <div - className={ - 'mx-auto w-full pb-[58px] lg:grid lg:grid-cols-12 lg:gap-x-2 lg:pb-0 xl:max-w-7xl xl:gap-x-8' - } - > - <Toaster /> - <GroupSidebar - groupName={group.name} - className="sticky top-0 hidden divide-gray-300 self-start pl-2 lg:col-span-2 lg:flex" - onClick={onSidebarClick} - joinOrAddQuestionsButton={joinOrAddQuestionsButton} - currentKey={sidebarPages[sidebarIndex].key} - /> - - <SEO - title={group.name} - description={`Created by ${creator.name}. ${group.about}`} - url={groupPath(group.slug)} - /> - <main className={'px-2 pt-1 lg:col-span-8 lg:pt-6 xl:col-span-8'}> - {pageContent} - </main> - </div> + <TopGroupNavBar group={group} /> + <div className={'relative p-2 pt-0 md:pt-2'}> + <Tabs className={'mb-2'} tabs={tabs} /> </div> - </> + </Page> ) } -export function TopGroupNavBar(props: { - group: Group - currentPage: string - onClick: (key: string) => void -}) { +export function TopGroupNavBar(props: { group: Group }) { return ( <header className="sticky top-0 z-50 w-full border-b border-gray-200 md:hidden lg:col-span-12"> <div className="flex items-center bg-white px-4"> @@ -318,7 +268,6 @@ export function TopGroupNavBar(props: { </h1> </div> </div> - <GroupNavBar currentPage={props.currentPage} onClick={props.onClick} /> </header> ) } @@ -331,11 +280,13 @@ function JoinOrAddQuestionsButtons(props: { }) { const { group, user, isMember } = props return user && isMember ? ( - <Row className={'w-full self-start pt-4'}> + <Row className={'mb-2 w-full self-start md:mt-2 '}> <AddContractButton group={group} user={user} /> </Row> ) : group.anyoneCanJoin ? ( - <JoinGroupButton group={group} user={user} /> + <div className="mb-2 md:mb-0"> + <JoinGroupButton group={group} user={user} /> + </div> ) : null } diff --git a/web/pages/groups.tsx b/web/pages/groups.tsx index 1854da34..49d99d18 100644 --- a/web/pages/groups.tsx +++ b/web/pages/groups.tsx @@ -99,6 +99,7 @@ export default function Groups(props: { </div> <Tabs + className="mb-4" currentPageForAnalytics={'groups'} tabs={[ ...(user diff --git a/web/pages/leaderboards.tsx b/web/pages/leaderboards.tsx index 4f1e9437..623d21c8 100644 --- a/web/pages/leaderboards.tsx +++ b/web/pages/leaderboards.tsx @@ -132,6 +132,7 @@ export default function Leaderboards(_props: { /> <Title text={'Leaderboards'} className={'hidden md:block'} /> <Tabs + className="mb-4" currentPageForAnalytics={'leaderboards'} defaultIndex={1} tabs={[ diff --git a/web/pages/stats.tsx b/web/pages/stats.tsx index 40847470..19fab509 100644 --- a/web/pages/stats.tsx +++ b/web/pages/stats.tsx @@ -26,6 +26,7 @@ export default function Analytics() { return ( <Page> <Tabs + className="mb-4" currentPageForAnalytics={'stats'} tabs={[ { @@ -89,6 +90,7 @@ export function CustomAnalytics(props: Stats) { <Spacer h={4} /> <Tabs + className="mb-4" defaultIndex={1} tabs={[ { @@ -141,6 +143,7 @@ export function CustomAnalytics(props: Stats) { period? </p> <Tabs + className="mb-4" defaultIndex={1} tabs={[ { @@ -198,6 +201,7 @@ export function CustomAnalytics(props: Stats) { <Spacer h={4} /> <Tabs + className="mb-4" defaultIndex={2} tabs={[ { @@ -239,6 +243,7 @@ export function CustomAnalytics(props: Stats) { <Title text="Daily activity" /> <Tabs + className="mb-4" defaultIndex={0} tabs={[ { @@ -293,6 +298,7 @@ export function CustomAnalytics(props: Stats) { <Spacer h={4} /> <Tabs + className="mb-4" defaultIndex={1} tabs={[ { @@ -323,6 +329,7 @@ export function CustomAnalytics(props: Stats) { <Title text="Ratio of Active Users" /> <Tabs + className="mb-4" defaultIndex={1} tabs={[ { @@ -367,6 +374,7 @@ export function CustomAnalytics(props: Stats) { Sum of bet amounts. (Divided by 100 to be more readable.) </p> <Tabs + className="mb-4" defaultIndex={1} tabs={[ { From 06db5515f6ab7b2795d3ece211d2e2c73b8e901a Mon Sep 17 00:00:00 2001 From: mantikoros <sgrugett@gmail.com> Date: Thu, 22 Sep 2022 14:01:37 -0400 Subject: [PATCH 13/60] add qr code to share dialog --- web/components/contract/share-modal.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/components/contract/share-modal.tsx b/web/components/contract/share-modal.tsx index e1eb26eb..88cdfb8b 100644 --- a/web/components/contract/share-modal.tsx +++ b/web/components/contract/share-modal.tsx @@ -21,6 +21,7 @@ import { CreateChallengeModal } from 'web/components/challenges/create-challenge import { useState } from 'react' import { CHALLENGES_ENABLED } from 'common/challenge' import ChallengeIcon from 'web/lib/icons/challenge-icon' +import { QRCode } from '../qr-code' export function ShareModal(props: { contract: Contract @@ -54,6 +55,7 @@ export function ShareModal(props: { </SiteLink>{' '} if a new user signs up using the link! </p> + <QRCode url={shareUrl} className="self-center" width={150} height={150} /> <Button size="2xl" color="indigo" @@ -69,6 +71,7 @@ export function ShareModal(props: { {linkIcon} Copy link </Button> + <Row className="z-0 flex-wrap justify-center gap-4 self-center"> <TweetButton className="self-start" From 0c0e7b558271c7d4551eb4b4361afc48b9aa1803 Mon Sep 17 00:00:00 2001 From: mantikoros <mantikoros@users.noreply.github.com> Date: Thu, 22 Sep 2022 18:02:17 +0000 Subject: [PATCH 14/60] Auto-prettification --- web/components/contract/share-modal.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/web/components/contract/share-modal.tsx b/web/components/contract/share-modal.tsx index 88cdfb8b..72c7aba3 100644 --- a/web/components/contract/share-modal.tsx +++ b/web/components/contract/share-modal.tsx @@ -55,7 +55,12 @@ export function ShareModal(props: { </SiteLink>{' '} if a new user signs up using the link! </p> - <QRCode url={shareUrl} className="self-center" width={150} height={150} /> + <QRCode + url={shareUrl} + className="self-center" + width={150} + height={150} + /> <Button size="2xl" color="indigo" @@ -71,7 +76,6 @@ export function ShareModal(props: { {linkIcon} Copy link </Button> - <Row className="z-0 flex-wrap justify-center gap-4 self-center"> <TweetButton className="self-start" From b9fffcfa305c6b10c1fb0c006c429e83c70ff24e Mon Sep 17 00:00:00 2001 From: mantikoros <sgrugett@gmail.com> Date: Thu, 22 Sep 2022 14:20:37 -0400 Subject: [PATCH 15/60] sort: add back 24h volume, remove most traded --- web/components/contract-search.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index 4b14d4a7..919cce86 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -48,7 +48,7 @@ import { Title } from './title' export const SORTS = [ { label: 'Newest', value: 'newest' }, { label: 'Trending', value: 'score' }, - { label: `Most traded`, value: 'most-traded' }, + { label: '24h volume', value: '24-hour-vol' }, { label: 'Last updated', value: 'last-updated' }, { label: 'Closing soon', value: 'close-date' }, { label: 'Resolve date', value: 'resolve-date' }, From 6fe0a22a4867f789e8e7d2109a5fb8054625f1a6 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Thu, 22 Sep 2022 12:40:27 -0700 Subject: [PATCH 16/60] Improve contract leaderboard computation (#918) * Fix and clean up top comment stuff * Make leaderboard code generic on entry type * No need to look up users on contract leaderboard --- .../contract/contract-leaderboard.tsx | 70 +++++++------------ web/components/leaderboard.tsx | 31 ++++---- web/pages/group/[...slugs]/index.tsx | 2 +- web/pages/leaderboards.tsx | 6 +- 4 files changed, 48 insertions(+), 61 deletions(-) diff --git a/web/components/contract/contract-leaderboard.tsx b/web/components/contract/contract-leaderboard.tsx index 6cd2ae62..f984e3b6 100644 --- a/web/components/contract/contract-leaderboard.tsx +++ b/web/components/contract/contract-leaderboard.tsx @@ -3,9 +3,8 @@ import { resolvedPayout } from 'common/calculate' import { Contract } from 'common/contract' import { formatMoney } from 'common/util/format' import { groupBy, mapValues, sumBy, sortBy, keyBy } from 'lodash' -import { useState, useMemo, useEffect } from 'react' +import { memo } from 'react' import { useComments } from 'web/hooks/use-comments' -import { listUsers, User } from 'web/lib/firebase/users' import { FeedBet } from '../feed/feed-bets' import { FeedComment } from '../feed/feed-comments' import { Spacer } from '../layout/spacer' @@ -13,59 +12,48 @@ import { Leaderboard } from '../leaderboard' import { Title } from '../title' import { BETTORS } from 'common/user' -export function ContractLeaderboard(props: { +export const ContractLeaderboard = memo(function ContractLeaderboard(props: { contract: Contract bets: Bet[] }) { const { contract, bets } = props - const [users, setUsers] = useState<User[]>() - const { userProfits, top5Ids } = useMemo(() => { - // Create a map of userIds to total profits (including sales) - const openBets = bets.filter((bet) => !bet.isSold && !bet.sale) - const betsByUser = groupBy(openBets, 'userId') - - const userProfits = mapValues(betsByUser, (bets) => - sumBy(bets, (bet) => resolvedPayout(contract, bet) - bet.amount) - ) - // Find the 5 users with the most profits - const top5Ids = Object.entries(userProfits) - .sort(([_i1, p1], [_i2, p2]) => p2 - p1) - .filter(([, p]) => p > 0) - .slice(0, 5) - .map(([id]) => id) - return { userProfits, top5Ids } - }, [contract, bets]) - - useEffect(() => { - if (top5Ids.length > 0) { - listUsers(top5Ids).then((users) => { - const sortedUsers = sortBy(users, (user) => -userProfits[user.id]) - setUsers(sortedUsers) - }) + // Create a map of userIds to total profits (including sales) + const openBets = bets.filter((bet) => !bet.isSold && !bet.sale) + const betsByUser = groupBy(openBets, 'userId') + const userProfits = mapValues(betsByUser, (bets) => { + return { + name: bets[0].userName, + username: bets[0].userUsername, + avatarUrl: bets[0].userAvatarUrl, + total: sumBy(bets, (bet) => resolvedPayout(contract, bet) - bet.amount), } - }, [userProfits, top5Ids]) + }) + // Find the 5 users with the most profits + const top5 = Object.values(userProfits) + .sort((p1, p2) => p2.total - p1.total) + .filter((p) => p.total > 0) + .slice(0, 5) - return users && users.length > 0 ? ( + return top5 && top5.length > 0 ? ( <Leaderboard title={`🏅 Top ${BETTORS}`} - users={users || []} + entries={top5 || []} columns={[ { header: 'Total profit', - renderCell: (user) => formatMoney(userProfits[user.id] || 0), + renderCell: (entry) => formatMoney(entry.total), }, ]} className="mt-12 max-w-sm" /> ) : null -} +}) export function ContractTopTrades(props: { contract: Contract; bets: Bet[] }) { const { contract, bets } = props // todo: this stuff should be calced in DB at resolve time const comments = useComments(contract.id) - const commentsById = keyBy(comments, 'id') const betsById = keyBy(bets, 'id') // If 'id2' is the sale of 'id1', both are logged with (id2 - id1) of profit @@ -86,29 +74,23 @@ export function ContractTopTrades(props: { contract: Contract; bets: Bet[] }) { const topBetId = sortBy(bets, (b) => -profitById[b.id])[0]?.id const topBettor = betsById[topBetId]?.userName - // And also the commentId of the comment with the highest profit - const topCommentId = sortBy( - comments, - (c) => c.betId && -profitById[c.betId] - )[0]?.id + // And also the comment with the highest profit + const topComment = sortBy(comments, (c) => c.betId && -profitById[c.betId])[0] return ( <div className="mt-12 max-w-sm"> - {topCommentId && profitById[topCommentId] > 0 && ( + {topComment && profitById[topComment.id] > 0 && ( <> <Title text="💬 Proven correct" className="!mt-0" /> <div className="relative flex items-start space-x-3 rounded-md bg-gray-50 px-2 py-4"> - <FeedComment - contract={contract} - comment={commentsById[topCommentId]} - /> + <FeedComment contract={contract} comment={topComment} /> </div> <Spacer h={16} /> </> )} {/* If they're the same, only show the comment; otherwise show both */} - {topBettor && topBetId !== topCommentId && profitById[topBetId] > 0 && ( + {topBettor && topBetId !== topComment?.betId && profitById[topBetId] > 0 && ( <> <Title text="💸 Best bet" className="!mt-0" /> <div className="relative flex items-start space-x-3 rounded-md bg-gray-50 px-2 py-4"> diff --git a/web/components/leaderboard.tsx b/web/components/leaderboard.tsx index a0670795..1035e9d1 100644 --- a/web/components/leaderboard.tsx +++ b/web/components/leaderboard.tsx @@ -1,28 +1,33 @@ import clsx from 'clsx' -import { User } from 'common/user' import { Avatar } from './avatar' import { Row } from './layout/row' import { SiteLink } from './site-link' import { Title } from './title' -export function Leaderboard(props: { +interface LeaderboardEntry { + username: string + name: string + avatarUrl?: string +} + +export function Leaderboard<T extends LeaderboardEntry>(props: { title: string - users: User[] + entries: T[] columns: { header: string - renderCell: (user: User) => any + renderCell: (entry: T) => any }[] className?: string maxToShow?: number }) { // TODO: Ideally, highlight your own entry on the leaderboard const { title, columns, className } = props - const maxToShow = props.maxToShow ?? props.users.length - const users = props.users.slice(0, maxToShow) + const maxToShow = props.maxToShow ?? props.entries.length + const entries = props.entries.slice(0, maxToShow) return ( <div className={clsx('w-full px-1', className)}> <Title text={title} className="!mt-0" /> - {users.length === 0 ? ( + {entries.length === 0 ? ( <div className="ml-2 text-gray-500">None yet</div> ) : ( <div className="overflow-x-auto"> @@ -37,19 +42,19 @@ export function Leaderboard(props: { </tr> </thead> <tbody> - {users.map((user, index) => ( - <tr key={user.id}> + {entries.map((entry, index) => ( + <tr key={index}> <td>{index + 1}</td> <td className="max-w-[190px]"> - <SiteLink className="relative" href={`/${user.username}`}> + <SiteLink className="relative" href={`/${entry.username}`}> <Row className="items-center gap-4"> - <Avatar avatarUrl={user.avatarUrl} size={8} /> - <div className="truncate">{user.name}</div> + <Avatar avatarUrl={entry.avatarUrl} size={8} /> + <div className="truncate">{entry.name}</div> </Row> </SiteLink> </td> {columns.map((column) => ( - <td key={column.header}>{column.renderCell(user)}</td> + <td key={column.header}>{column.renderCell(entry)}</td> ))} </tr> ))} diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index 779677c4..f06247cd 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -403,7 +403,7 @@ function GroupLeaderboard(props: { return ( <Leaderboard className="max-w-xl" - users={topUsers.map((t) => t.user)} + entries={topUsers.map((t) => t.user)} title={title} columns={[ { header, renderCell: (user) => formatMoney(scoresByUser[user.id]) }, diff --git a/web/pages/leaderboards.tsx b/web/pages/leaderboards.tsx index 623d21c8..e663d81c 100644 --- a/web/pages/leaderboards.tsx +++ b/web/pages/leaderboards.tsx @@ -81,7 +81,7 @@ export default function Leaderboards(_props: { <Col className="mx-4 items-center gap-10 lg:flex-row"> <Leaderboard title={`🏅 Top ${BETTORS}`} - users={topTraders} + entries={topTraders} columns={[ { header: 'Total profit', @@ -92,7 +92,7 @@ export default function Leaderboards(_props: { <Leaderboard title="🏅 Top creators" - users={topCreators} + entries={topCreators} columns={[ { header: 'Total bet', @@ -106,7 +106,7 @@ export default function Leaderboards(_props: { <Col className="mx-4 my-10 items-center gap-10 lg:mx-0 lg:w-1/2 lg:flex-row"> <Leaderboard title="🏅 Top followed" - users={topFollowed} + entries={topFollowed} columns={[ { header: 'Total followers', From 6ee8d90bdb8a12657471b41dc48507a96c5001b3 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Thu, 22 Sep 2022 12:40:44 -0700 Subject: [PATCH 17/60] Eliminate redundant showReply/replyTo state (#917) --- web/components/comment-input.tsx | 15 ++++--- .../feed/feed-answer-comment-group.tsx | 39 +++++++------------ web/components/feed/feed-comments.tsx | 30 +++++++------- web/posts/post-comments.tsx | 2 +- 4 files changed, 35 insertions(+), 51 deletions(-) diff --git a/web/components/comment-input.tsx b/web/components/comment-input.tsx index bf3730f3..d13ebf3b 100644 --- a/web/components/comment-input.tsx +++ b/web/components/comment-input.tsx @@ -11,7 +11,7 @@ import { Row } from './layout/row' import { LoadingIndicator } from './loading-indicator' export function CommentInput(props: { - replyToUser?: { id: string; username: string } + replyTo?: { id: string; username: string } // Reply to a free response answer parentAnswerOutcome?: string // Reply to another comment @@ -19,7 +19,7 @@ export function CommentInput(props: { onSubmitComment?: (editor: Editor) => void className?: string }) { - const { parentAnswerOutcome, parentCommentId, replyToUser, onSubmitComment } = + const { parentAnswerOutcome, parentCommentId, replyTo, onSubmitComment } = props const user = useUser() @@ -55,7 +55,7 @@ export function CommentInput(props: { <CommentInputTextArea editor={editor} upload={upload} - replyToUser={replyToUser} + replyTo={replyTo} user={user} submitComment={submitComment} isSubmitting={isSubmitting} @@ -67,14 +67,13 @@ export function CommentInput(props: { export function CommentInputTextArea(props: { user: User | undefined | null - replyToUser?: { id: string; username: string } + replyTo?: { id: string; username: string } editor: Editor | null upload: Parameters<typeof TextEditor>[0]['upload'] submitComment: () => void isSubmitting: boolean }) { - const { user, editor, upload, submitComment, isSubmitting, replyToUser } = - props + const { user, editor, upload, submitComment, isSubmitting, replyTo } = props useEffect(() => { editor?.setEditable(!isSubmitting) }, [isSubmitting, editor]) @@ -108,12 +107,12 @@ export function CommentInputTextArea(props: { }, }) // insert at mention and focus - if (replyToUser) { + if (replyTo) { editor .chain() .setContent({ type: 'mention', - attrs: { label: replyToUser.username, id: replyToUser.id }, + attrs: { label: replyTo.username, id: replyTo.id }, }) .insertContent(' ') .focus() diff --git a/web/components/feed/feed-answer-comment-group.tsx b/web/components/feed/feed-answer-comment-group.tsx index 27f0f731..b4f822cb 100644 --- a/web/components/feed/feed-answer-comment-group.tsx +++ b/web/components/feed/feed-answer-comment-group.tsx @@ -10,11 +10,10 @@ import clsx from 'clsx' import { ContractCommentInput, FeedComment, + ReplyTo, } from 'web/components/feed/feed-comments' import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time' import { useRouter } from 'next/router' -import { User } from 'common/user' -import { useEvent } from 'web/hooks/use-event' import { CommentTipMap } from 'web/hooks/use-tip-txns' import { UserLink } from 'web/components/user-link' @@ -27,27 +26,11 @@ export function FeedAnswerCommentGroup(props: { const { answer, contract, answerComments, tips } = props const { username, avatarUrl, name, text } = answer - const [replyToUser, setReplyToUser] = - useState<Pick<User, 'id' | 'username'>>() - const [showReply, setShowReply] = useState(false) + const [replyTo, setReplyTo] = useState<ReplyTo>() const [highlighted, setHighlighted] = useState(false) const router = useRouter() - const answerElementId = `answer-${answer.id}` - const scrollAndOpenReplyInput = useEvent( - (comment?: ContractComment, answer?: Answer) => { - setReplyToUser( - comment - ? { id: comment.userId, username: comment.userUsername } - : answer - ? { id: answer.userId, username: answer.username } - : undefined - ) - setShowReply(true) - } - ) - useEffect(() => { if (router.asPath.endsWith(`#${answerElementId}`)) { setHighlighted(true) @@ -83,7 +66,9 @@ export function FeedAnswerCommentGroup(props: { <div className="sm:hidden"> <button className="text-xs font-bold text-gray-500 hover:underline" - onClick={() => scrollAndOpenReplyInput(undefined, answer)} + onClick={() => + setReplyTo({ id: answer.id, username: answer.username }) + } > Reply </button> @@ -92,7 +77,9 @@ export function FeedAnswerCommentGroup(props: { <div className="justify-initial hidden sm:block"> <button className="text-xs font-bold text-gray-500 hover:underline" - onClick={() => scrollAndOpenReplyInput(undefined, answer)} + onClick={() => + setReplyTo({ id: answer.id, username: answer.username }) + } > Reply </button> @@ -107,11 +94,13 @@ export function FeedAnswerCommentGroup(props: { contract={contract} comment={comment} tips={tips[comment.id] ?? {}} - onReplyClick={scrollAndOpenReplyInput} + onReplyClick={() => + setReplyTo({ id: comment.id, username: comment.userUsername }) + } /> ))} </Col> - {showReply && ( + {replyTo && ( <div className="relative ml-7"> <span className="absolute -left-1 -ml-[1px] mt-[1.25rem] h-2 w-0.5 rotate-90 bg-gray-200" @@ -120,8 +109,8 @@ export function FeedAnswerCommentGroup(props: { <ContractCommentInput contract={contract} parentAnswerOutcome={answer.number.toString()} - replyToUser={replyToUser} - onSubmitComment={() => setShowReply(false)} + replyTo={replyTo} + onSubmitComment={() => setReplyTo(undefined)} /> </div> )} diff --git a/web/components/feed/feed-comments.tsx b/web/components/feed/feed-comments.tsx index acb48ec1..94cea452 100644 --- a/web/components/feed/feed-comments.tsx +++ b/web/components/feed/feed-comments.tsx @@ -20,6 +20,8 @@ import { Editor } from '@tiptap/react' import { UserLink } from 'web/components/user-link' import { CommentInput } from '../comment-input' +export type ReplyTo = { id: string; username: string } + export function FeedCommentThread(props: { contract: Contract threadComments: ContractComment[] @@ -27,13 +29,7 @@ export function FeedCommentThread(props: { parentComment: ContractComment }) { const { contract, threadComments, tips, parentComment } = props - const [showReply, setShowReply] = useState(false) - const [replyTo, setReplyTo] = useState<{ id: string; username: string }>() - - function scrollAndOpenReplyInput(comment: ContractComment) { - setReplyTo({ id: comment.userId, username: comment.userUsername }) - setShowReply(true) - } + const [replyTo, setReplyTo] = useState<ReplyTo>() return ( <Col className="relative w-full items-stretch gap-3 pb-4"> @@ -48,10 +44,12 @@ export function FeedCommentThread(props: { contract={contract} comment={comment} tips={tips[comment.id] ?? {}} - onReplyClick={scrollAndOpenReplyInput} + onReplyClick={() => + setReplyTo({ id: comment.id, username: comment.userUsername }) + } /> ))} - {showReply && ( + {replyTo && ( <Col className="-pb-2 relative ml-6"> <span className="absolute -left-1 -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90 bg-gray-200" @@ -60,10 +58,8 @@ export function FeedCommentThread(props: { <ContractCommentInput contract={contract} parentCommentId={parentComment.id} - replyToUser={replyTo} - onSubmitComment={() => { - setShowReply(false) - }} + replyTo={replyTo} + onSubmitComment={() => setReplyTo(undefined)} /> </Col> )} @@ -76,7 +72,7 @@ export function FeedComment(props: { comment: ContractComment tips?: CommentTips indent?: boolean - onReplyClick?: (comment: ContractComment) => void + onReplyClick?: () => void }) { const { contract, comment, tips, indent, onReplyClick } = props const { @@ -174,7 +170,7 @@ export function FeedComment(props: { {onReplyClick && ( <button className="font-bold hover:underline" - onClick={() => onReplyClick(comment)} + onClick={onReplyClick} > Reply </button> @@ -204,7 +200,7 @@ export function ContractCommentInput(props: { contract: Contract className?: string parentAnswerOutcome?: string | undefined - replyToUser?: { id: string; username: string } + replyTo?: ReplyTo parentCommentId?: string onSubmitComment?: () => void }) { @@ -226,7 +222,7 @@ export function ContractCommentInput(props: { return ( <CommentInput - replyToUser={props.replyToUser} + replyTo={props.replyTo} parentAnswerOutcome={props.parentAnswerOutcome} parentCommentId={props.parentCommentId} onSubmitComment={onSubmitComment} diff --git a/web/posts/post-comments.tsx b/web/posts/post-comments.tsx index d129f807..b98887bb 100644 --- a/web/posts/post-comments.tsx +++ b/web/posts/post-comments.tsx @@ -92,7 +92,7 @@ export function PostCommentInput(props: { return ( <CommentInput - replyToUser={replyToUser} + replyTo={replyToUser} parentCommentId={parentCommentId} onSubmitComment={onSubmitComment} /> From 721448f40811889cb8780f7c1ea5c537fbbc4fb1 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Thu, 22 Sep 2022 12:40:55 -0700 Subject: [PATCH 18/60] Clean up and fix stuff on answers panel (#914) --- web/components/answers/answers-panel.tsx | 41 ++++++++---------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/web/components/answers/answers-panel.tsx b/web/components/answers/answers-panel.tsx index a1cef4c3..51cf5799 100644 --- a/web/components/answers/answers-panel.tsx +++ b/web/components/answers/answers-panel.tsx @@ -38,26 +38,13 @@ export function AnswersPanel(props: { const answers = (useAnswers(contract.id) ?? contract.answers).filter( (a) => a.number != 0 || contract.outcomeType === 'MULTIPLE_CHOICE' ) - const hasZeroBetAnswers = answers.some((answer) => totalBets[answer.id] < 1) - - const [winningAnswers, losingAnswers] = partition( - answers.filter((a) => (showAllAnswers ? true : totalBets[a.id] > 0)), - (answer) => - answer.id === resolution || (resolutions && resolutions[answer.id]) + const [winningAnswers, notWinningAnswers] = partition( + answers, + (a) => a.id === resolution || (resolutions && resolutions[a.id]) ) - const sortedAnswers = [ - ...sortBy(winningAnswers, (answer) => - resolutions ? -1 * resolutions[answer.id] : 0 - ), - ...sortBy( - resolution ? [] : losingAnswers, - (answer) => -1 * getDpmOutcomeProbability(contract.totalShares, answer.id) - ), - ] - - const answerItems = sortBy( - losingAnswers.length > 0 ? losingAnswers : sortedAnswers, - (answer) => -getOutcomeProbability(contract, answer.id) + const [visibleAnswers, invisibleAnswers] = partition( + sortBy(notWinningAnswers, (a) => -getOutcomeProbability(contract, a.id)), + (a) => showAllAnswers || totalBets[a.id] > 0 ) const user = useUser() @@ -107,13 +94,13 @@ export function AnswersPanel(props: { return ( <Col className="gap-3"> {(resolveOption || resolution) && - sortedAnswers.map((answer) => ( + sortBy(winningAnswers, (a) => -(resolutions?.[a.id] ?? 0)).map((a) => ( <AnswerItem - key={answer.id} - answer={answer} + key={a.id} + answer={a} contract={contract} showChoice={showChoice} - chosenProb={chosenAnswers[answer.id]} + chosenProb={chosenAnswers[a.id]} totalChosenProb={chosenTotal} onChoose={onChoose} onDeselect={onDeselect} @@ -127,10 +114,10 @@ export function AnswersPanel(props: { tradingAllowed(contract) ? '' : '-mb-6' )} > - {answerItems.map((item) => ( - <OpenAnswer key={item.id} answer={item} contract={contract} /> + {visibleAnswers.map((a) => ( + <OpenAnswer key={a.id} answer={a} contract={contract} /> ))} - {hasZeroBetAnswers && !showAllAnswers && ( + {invisibleAnswers.length > 0 && !showAllAnswers && ( <Button className="self-end" color="gray-white" @@ -143,7 +130,7 @@ export function AnswersPanel(props: { </Col> )} - {answers.length <= 1 && ( + {answers.length === 0 && ( <div className="pb-4 text-gray-500">No answers yet...</div> )} From 7704de6904743a40f20f47d0e505b939381bdb14 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Thu, 22 Sep 2022 12:46:48 -0700 Subject: [PATCH 19/60] Next.js 12.2.5 -> 12.3.1 (#922) --- web/components/auth-context.tsx | 2 +- web/components/avatar.tsx | 2 +- web/components/landing-page-panel.tsx | 1 + web/next.config.js | 3 - web/package.json | 2 +- web/pages/_app.tsx | 9 +- yarn.lock | 175 +++++++++++++------------- 7 files changed, 100 insertions(+), 94 deletions(-) diff --git a/web/components/auth-context.tsx b/web/components/auth-context.tsx index d7c7b717..19ced0b2 100644 --- a/web/components/auth-context.tsx +++ b/web/components/auth-context.tsx @@ -17,7 +17,7 @@ import { setCookie } from 'web/lib/util/cookie' // Either we haven't looked up the logged in user yet (undefined), or we know // the user is not logged in (null), or we know the user is logged in. -type AuthUser = undefined | null | UserAndPrivateUser +export type AuthUser = undefined | null | UserAndPrivateUser const TEN_YEARS_SECS = 60 * 60 * 24 * 365 * 10 const CACHED_USER_KEY = 'CACHED_USER_KEY_V2' diff --git a/web/components/avatar.tsx b/web/components/avatar.tsx index 44c37128..abb67d46 100644 --- a/web/components/avatar.tsx +++ b/web/components/avatar.tsx @@ -40,7 +40,7 @@ export function Avatar(props: { style={{ maxWidth: `${s * 0.25}rem` }} src={avatarUrl} onClick={onClick} - alt={username} + alt={`${username ?? 'Unknown user'} avatar`} onError={() => { // If the image doesn't load, clear the avatarUrl to show the default // Mostly for localhost, when getting a 403 from googleusercontent diff --git a/web/components/landing-page-panel.tsx b/web/components/landing-page-panel.tsx index f0dae17d..54e501b2 100644 --- a/web/components/landing-page-panel.tsx +++ b/web/components/landing-page-panel.tsx @@ -23,6 +23,7 @@ export function LandingPagePanel(props: { hotContracts: Contract[] }) { height={250} width={250} className="self-center" + alt="Manifold logo" src="/flappy-logo.gif" /> <div className="m-4 max-w-[550px] self-center"> diff --git a/web/next.config.js b/web/next.config.js index 21b375ba..cf727fd4 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -9,9 +9,6 @@ module.exports = { reactStrictMode: true, optimizeFonts: false, experimental: { - images: { - allowFutureImage: true, - }, scrollRestoration: true, externalDir: true, modularizeImports: { diff --git a/web/package.json b/web/package.json index ba25a6e1..6ee29183 100644 --- a/web/package.json +++ b/web/package.json @@ -46,7 +46,7 @@ "gridjs-react": "5.0.2", "lodash": "4.17.21", "nanoid": "^3.3.4", - "next": "12.2.5", + "next": "12.3.1", "node-fetch": "3.2.4", "prosemirror-state": "1.4.1", "react": "17.0.2", diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index d5a38272..3e82d029 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -4,7 +4,7 @@ import { useEffect } from 'react' import Head from 'next/head' import Script from 'next/script' import { QueryClient, QueryClientProvider } from 'react-query' -import { AuthProvider } from 'web/components/auth-context' +import { AuthProvider, AuthUser } from 'web/components/auth-context' import Welcome from 'web/components/onboarding/welcome' function firstLine(msg: string) { @@ -24,7 +24,10 @@ function printBuildInfo() { } } -function MyApp({ Component, pageProps }: AppProps) { +// specially treated props that may be present in the server/static props +type ManifoldPageProps = { auth?: AuthUser } + +function MyApp({ Component, pageProps }: AppProps<ManifoldPageProps>) { useEffect(printBuildInfo, []) return ( @@ -78,7 +81,7 @@ function MyApp({ Component, pageProps }: AppProps) { </Head> <AuthProvider serverUser={pageProps.auth}> <QueryClientProvider client={queryClient}> - <Welcome {...pageProps} /> + <Welcome /> <Component {...pageProps} /> </QueryClientProvider> </AuthProvider> diff --git a/yarn.lock b/yarn.lock index 89d43cba..81cf80fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2476,10 +2476,10 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== -"@next/env@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3" - integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw== +"@next/env@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.1.tgz#18266bd92de3b4aa4037b1927aa59e6f11879260" + integrity sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg== "@next/eslint-plugin-next@12.1.6": version "12.1.6" @@ -2488,70 +2488,70 @@ dependencies: glob "7.1.7" -"@next/swc-android-arm-eabi@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d" - integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA== +"@next/swc-android-arm-eabi@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz#b15ce8ad376102a3b8c0f3c017dde050a22bb1a3" + integrity sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ== -"@next/swc-android-arm64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792" - integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg== +"@next/swc-android-arm64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz#85d205f568a790a137cb3c3f720d961a2436ac9c" + integrity sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q== -"@next/swc-darwin-arm64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d" - integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg== +"@next/swc-darwin-arm64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz#b105457d6760a7916b27e46c97cb1a40547114ae" + integrity sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg== -"@next/swc-darwin-x64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd" - integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A== +"@next/swc-darwin-x64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz#6947b39082271378896b095b6696a7791c6e32b1" + integrity sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA== -"@next/swc-freebsd-x64@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd" - integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw== +"@next/swc-freebsd-x64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz#2b6c36a4d84aae8b0ea0e0da9bafc696ae27085a" + integrity sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q== -"@next/swc-linux-arm-gnueabihf@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9" - integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg== +"@next/swc-linux-arm-gnueabihf@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz#6e421c44285cfedac1f4631d5de330dd60b86298" + integrity sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w== -"@next/swc-linux-arm64-gnu@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f" - integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ== +"@next/swc-linux-arm64-gnu@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz#8863f08a81f422f910af126159d2cbb9552ef717" + integrity sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ== -"@next/swc-linux-arm64-musl@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383" - integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg== +"@next/swc-linux-arm64-musl@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz#0038f07cf0b259d70ae0c80890d826dfc775d9f3" + integrity sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg== -"@next/swc-linux-x64-gnu@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e" - integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw== +"@next/swc-linux-x64-gnu@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz#c66468f5e8181ffb096c537f0dbfb589baa6a9c1" + integrity sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA== -"@next/swc-linux-x64-musl@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95" - integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g== +"@next/swc-linux-x64-musl@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz#c6269f3e96ac0395bc722ad97ce410ea5101d305" + integrity sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg== -"@next/swc-win32-arm64-msvc@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97" - integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw== +"@next/swc-win32-arm64-msvc@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz#83c639ee969cee36ce247c3abd1d9df97b5ecade" + integrity sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw== -"@next/swc-win32-ia32-msvc@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19" - integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw== +"@next/swc-win32-ia32-msvc@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz#52995748b92aa8ad053440301bc2c0d9fbcf27c2" + integrity sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA== -"@next/swc-win32-x64-msvc@12.2.5": - version "12.2.5" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4" - integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q== +"@next/swc-win32-x64-msvc@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz#27d71a95247a9eaee03d47adee7e3bd594514136" + integrity sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA== "@nivo/annotations@0.74.0": version "0.74.0" @@ -2933,10 +2933,10 @@ "@svgr/plugin-jsx" "^6.2.1" "@svgr/plugin-svgo" "^6.2.0" -"@swc/helpers@0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012" - integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA== +"@swc/helpers@0.4.11": + version "0.4.11" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de" + integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw== dependencies: tslib "^2.4.0" @@ -4545,6 +4545,11 @@ caniuse-lite@^1.0.30001230, caniuse-lite@^1.0.30001332: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001341.tgz#59590c8ffa8b5939cf4161f00827b8873ad72498" integrity sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA== +caniuse-lite@^1.0.30001406: + version "1.0.30001409" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001409.tgz#6135da9dcab34cd9761d9cdb12a68e6740c5e96e" + integrity sha512-V0mnJ5dwarmhYv8/MzhJ//aW68UpvnQBXv8lJ2QUsvn2pHcmAuNtu8hQEDz37XnA1iE+lRR9CIfGWWpgJ5QedQ== + ccount@^1.0.0, ccount@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" @@ -8637,31 +8642,31 @@ next-sitemap@^2.5.14: "@corex/deepmerge" "^2.6.148" minimist "^1.2.6" -next@12.2.5: - version "12.2.5" - resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717" - integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA== +next@12.3.1: + version "12.3.1" + resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1" + integrity sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw== dependencies: - "@next/env" "12.2.5" - "@swc/helpers" "0.4.3" - caniuse-lite "^1.0.30001332" + "@next/env" "12.3.1" + "@swc/helpers" "0.4.11" + caniuse-lite "^1.0.30001406" postcss "8.4.14" - styled-jsx "5.0.4" + styled-jsx "5.0.7" use-sync-external-store "1.2.0" optionalDependencies: - "@next/swc-android-arm-eabi" "12.2.5" - "@next/swc-android-arm64" "12.2.5" - "@next/swc-darwin-arm64" "12.2.5" - "@next/swc-darwin-x64" "12.2.5" - "@next/swc-freebsd-x64" "12.2.5" - "@next/swc-linux-arm-gnueabihf" "12.2.5" - "@next/swc-linux-arm64-gnu" "12.2.5" - "@next/swc-linux-arm64-musl" "12.2.5" - "@next/swc-linux-x64-gnu" "12.2.5" - "@next/swc-linux-x64-musl" "12.2.5" - "@next/swc-win32-arm64-msvc" "12.2.5" - "@next/swc-win32-ia32-msvc" "12.2.5" - "@next/swc-win32-x64-msvc" "12.2.5" + "@next/swc-android-arm-eabi" "12.3.1" + "@next/swc-android-arm64" "12.3.1" + "@next/swc-darwin-arm64" "12.3.1" + "@next/swc-darwin-x64" "12.3.1" + "@next/swc-freebsd-x64" "12.3.1" + "@next/swc-linux-arm-gnueabihf" "12.3.1" + "@next/swc-linux-arm64-gnu" "12.3.1" + "@next/swc-linux-arm64-musl" "12.3.1" + "@next/swc-linux-x64-gnu" "12.3.1" + "@next/swc-linux-x64-musl" "12.3.1" + "@next/swc-win32-arm64-msvc" "12.3.1" + "@next/swc-win32-ia32-msvc" "12.3.1" + "@next/swc-win32-x64-msvc" "12.3.1" no-case@^3.0.4: version "3.0.4" @@ -11267,10 +11272,10 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -styled-jsx@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53" - integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ== +styled-jsx@5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48" + integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA== stylehacks@^5.1.0: version "5.1.0" From a1c3d0a2dde77024c2705c4bb98243d00d582580 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Thu, 22 Sep 2022 12:58:40 -0700 Subject: [PATCH 20/60] Fix up comment permalink stuff (#915) * Eliminate needless state/effects to highlight comments * Scroll to comment on render if highlighted --- web/components/feed/feed-answer-comment-group.tsx | 12 +++++++----- web/components/feed/feed-comments.tsx | 13 ++++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/web/components/feed/feed-answer-comment-group.tsx b/web/components/feed/feed-answer-comment-group.tsx index b4f822cb..e17ea578 100644 --- a/web/components/feed/feed-answer-comment-group.tsx +++ b/web/components/feed/feed-answer-comment-group.tsx @@ -1,7 +1,7 @@ import { Answer } from 'common/answer' import { FreeResponseContract } from 'common/contract' import { ContractComment } from 'common/comment' -import React, { useEffect, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { Col } from 'web/components/layout/col' import { Row } from 'web/components/layout/row' import { Avatar } from 'web/components/avatar' @@ -27,15 +27,16 @@ export function FeedAnswerCommentGroup(props: { const { username, avatarUrl, name, text } = answer const [replyTo, setReplyTo] = useState<ReplyTo>() - const [highlighted, setHighlighted] = useState(false) const router = useRouter() const answerElementId = `answer-${answer.id}` + const highlighted = router.asPath.endsWith(`#${answerElementId}`) + const answerRef = useRef<HTMLDivElement>(null) useEffect(() => { - if (router.asPath.endsWith(`#${answerElementId}`)) { - setHighlighted(true) + if (highlighted && answerRef.current != null) { + answerRef.current.scrollIntoView(true) } - }, [answerElementId, router.asPath]) + }, [highlighted]) return ( <Col className="relative flex-1 items-stretch gap-3"> @@ -44,6 +45,7 @@ export function FeedAnswerCommentGroup(props: { 'gap-3 space-x-3 pt-4 transition-all duration-1000', highlighted ? `-m-2 my-3 rounded bg-indigo-500/[0.2] p-2` : '' )} + ref={answerRef} id={answerElementId} > <Avatar username={username} avatarUrl={avatarUrl} /> diff --git a/web/components/feed/feed-comments.tsx b/web/components/feed/feed-comments.tsx index 94cea452..1b62690b 100644 --- a/web/components/feed/feed-comments.tsx +++ b/web/components/feed/feed-comments.tsx @@ -1,6 +1,6 @@ import { ContractComment } from 'common/comment' import { Contract } from 'common/contract' -import React, { useEffect, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { useUser } from 'web/hooks/use-user' import { formatMoney } from 'common/util/format' import { useRouter } from 'next/router' @@ -94,16 +94,19 @@ export function FeedComment(props: { money = formatMoney(Math.abs(comment.betAmount)) } - const [highlighted, setHighlighted] = useState(false) const router = useRouter() + const highlighted = router.asPath.endsWith(`#${comment.id}`) + const commentRef = useRef<HTMLDivElement>(null) + useEffect(() => { - if (router.asPath.endsWith(`#${comment.id}`)) { - setHighlighted(true) + if (highlighted && commentRef.current != null) { + commentRef.current.scrollIntoView(true) } - }, [comment.id, router.asPath]) + }, [highlighted]) return ( <Row + ref={commentRef} id={comment.id} className={clsx( 'relative', From 2240db9baaaab63fa3235eb9f756535b4a228c74 Mon Sep 17 00:00:00 2001 From: Sinclair Chen <abc.sinclair@gmail.com> Date: Thu, 22 Sep 2022 16:24:30 -0400 Subject: [PATCH 21/60] fix profile tab styling --- web/components/layout/tabs.tsx | 2 +- web/components/user-page.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/web/components/layout/tabs.tsx b/web/components/layout/tabs.tsx index 45e7e297..980a3cfc 100644 --- a/web/components/layout/tabs.tsx +++ b/web/components/layout/tabs.tsx @@ -31,7 +31,7 @@ export function ControlledTabs(props: TabProps & { activeIndex: number }) { return ( <> <nav - className={clsx(' space-x-8 border-b border-gray-200', className)} + className={clsx('space-x-8 border-b border-gray-200', className)} aria-label="Tabs" > {tabs.map((tab, i) => ( diff --git a/web/components/user-page.tsx b/web/components/user-page.tsx index 2b24fa60..f9845fbe 100644 --- a/web/components/user-page.tsx +++ b/web/components/user-page.tsx @@ -254,6 +254,7 @@ export function UserPage(props: { user: User }) { </Row> )} <QueryUncontrolledTabs + className="mb-4" currentPageForAnalytics={'profile'} labelClassName={'pb-2 pt-1 '} tabs={[ @@ -283,7 +284,7 @@ export function UserPage(props: { user: User }) { title: 'Stats', content: ( <Col className="mb-8"> - <Row className={'mb-8 flex-wrap items-center gap-6'}> + <Row className="mb-8 flex-wrap items-center gap-x-6 gap-y-2"> <FollowingButton user={user} /> <FollowersButton user={user} /> <ReferralsButton user={user} /> From eaaa46294af242e5d0c7ffaa5b3abc08be0b8032 Mon Sep 17 00:00:00 2001 From: Sinclair Chen <abc.sinclair@gmail.com> Date: Thu, 22 Sep 2022 17:07:51 -0400 Subject: [PATCH 22/60] fix empty comment send button style --- web/components/comment-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/components/comment-input.tsx b/web/components/comment-input.tsx index d13ebf3b..3ba6f2ce 100644 --- a/web/components/comment-input.tsx +++ b/web/components/comment-input.tsx @@ -126,7 +126,7 @@ export function CommentInputTextArea(props: { <TextEditor editor={editor} upload={upload}> {user && !isSubmitting && ( <button - className="btn btn-ghost btn-sm px-2 disabled:bg-inherit disabled:text-gray-300" + className="btn btn-ghost btn-sm disabled:bg-inherit! px-2 disabled:text-gray-300" disabled={!editor || editor.isEmpty} onClick={submit} > From c6d034545ae39c038c606ade4259710a02ab2bcc Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Thu, 22 Sep 2022 16:57:48 -0500 Subject: [PATCH 23/60] Home: Prob change cards. Sort by daily score. (#925) * Add dailyScore: product of unique bettors (3 days) and probChanges.day * Increase memory and duration of scoreContracts * Home: Smaller prob change card for groups. Use dailyScore for sort order (algolia) * Add back hover --- common/contract.ts | 1 + functions/src/score-contracts.ts | 27 +++-- web/components/contract/contract-card.tsx | 34 ++++++ web/components/contract/contracts-grid.tsx | 50 ++++---- web/components/contract/prob-change-table.tsx | 24 ++-- web/hooks/use-contracts.ts | 28 ++++- web/hooks/use-group.ts | 2 +- web/hooks/use-prob-changes.tsx | 110 +++++++----------- web/lib/firebase/contracts.ts | 20 +--- web/lib/service/algolia.ts | 10 ++ web/pages/daily-movers.tsx | 7 +- web/pages/home/edit.tsx | 2 +- web/pages/home/index.tsx | 77 +++++++----- 13 files changed, 238 insertions(+), 154 deletions(-) diff --git a/common/contract.ts b/common/contract.ts index 2f71bab7..248c9745 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -57,6 +57,7 @@ export type Contract<T extends AnyContractType = AnyContractType> = { uniqueBettorIds?: string[] uniqueBettorCount?: number popularityScore?: number + dailyScore?: number followerCount?: number featuredOnHomeRank?: number likedByUserIds?: string[] diff --git a/functions/src/score-contracts.ts b/functions/src/score-contracts.ts index 57976ff2..52ef39d4 100644 --- a/functions/src/score-contracts.ts +++ b/functions/src/score-contracts.ts @@ -1,12 +1,14 @@ import * as functions from 'firebase-functions' import * as admin from 'firebase-admin' -import { Bet } from 'common/bet' import { uniq } from 'lodash' -import { Contract } from 'common/contract' +import { Bet } from '../../common/bet' +import { Contract } from '../../common/contract' import { log } from './utils' +import { removeUndefinedProps } from '../../common/util/object' -export const scoreContracts = functions.pubsub - .schedule('every 1 hours') +export const scoreContracts = functions + .runWith({ memory: '4GB', timeoutSeconds: 540 }) + .pubsub.schedule('every 1 hours') .onRun(async () => { await scoreContractsInternal() }) @@ -44,11 +46,22 @@ async function scoreContractsInternal() { const bettors = bets.docs .map((doc) => doc.data() as Bet) .map((bet) => bet.userId) - const score = uniq(bettors).length - if (contract.popularityScore !== score) + const popularityScore = uniq(bettors).length + + let dailyScore: number | undefined + if (contract.outcomeType === 'BINARY' && contract.mechanism === 'cpmm-1') { + const percentChange = Math.abs(contract.probChanges.day) + dailyScore = popularityScore * percentChange + } + + if ( + contract.popularityScore !== popularityScore || + contract.dailyScore !== dailyScore + ) { await firestore .collection('contracts') .doc(contract.id) - .update({ popularityScore: score }) + .update(removeUndefinedProps({ popularityScore, dailyScore })) + } } } diff --git a/web/components/contract/contract-card.tsx b/web/components/contract/contract-card.tsx index 367a5401..aa130321 100644 --- a/web/components/contract/contract-card.tsx +++ b/web/components/contract/contract-card.tsx @@ -7,6 +7,7 @@ import { Col } from '../layout/col' import { BinaryContract, Contract, + CPMMBinaryContract, FreeResponseContract, MultipleChoiceContract, NumericContract, @@ -32,6 +33,8 @@ import { track } from '@amplitude/analytics-browser' import { trackCallback } from 'web/lib/service/analytics' import { getMappedValue } from 'common/pseudo-numeric' import { Tooltip } from '../tooltip' +import { SiteLink } from '../site-link' +import { ProbChange } from './prob-change-table' export function ContractCard(props: { contract: Contract @@ -379,3 +382,34 @@ export function PseudoNumericResolutionOrExpectation(props: { </Col> ) } + +export function ContractCardProbChange(props: { + contract: CPMMBinaryContract + noLinkAvatar?: boolean + className?: string +}) { + const { contract, noLinkAvatar, className } = props + return ( + <Col + className={clsx( + className, + 'mb-4 rounded-lg bg-white shadow hover:bg-gray-100 hover:shadow-lg' + )} + > + <AvatarDetails + contract={contract} + className={'px-6 pt-4'} + noLink={noLinkAvatar} + /> + <Row className={clsx('items-start justify-between gap-4 ', className)}> + <SiteLink + className="pl-6 pr-0 pt-2 pb-4 font-semibold text-indigo-700" + href={contractPath(contract)} + > + <span className="line-clamp-3">{contract.question}</span> + </SiteLink> + <ProbChange className="py-2 pr-4" contract={contract} /> + </Row> + </Col> + ) +} diff --git a/web/components/contract/contracts-grid.tsx b/web/components/contract/contracts-grid.tsx index 3da9a5d5..4f573fb8 100644 --- a/web/components/contract/contracts-grid.tsx +++ b/web/components/contract/contracts-grid.tsx @@ -2,7 +2,7 @@ import { Contract } from 'web/lib/firebase/contracts' import { User } from 'web/lib/firebase/users' import { Col } from '../layout/col' import { SiteLink } from '../site-link' -import { ContractCard } from './contract-card' +import { ContractCard, ContractCardProbChange } from './contract-card' import { ShowTime } from './contract-details' import { ContractSearch } from '../contract-search' import { useCallback } from 'react' @@ -10,6 +10,7 @@ import clsx from 'clsx' import { LoadingIndicator } from '../loading-indicator' import { VisibilityObserver } from '../visibility-observer' import Masonry from 'react-masonry-css' +import { CPMMBinaryContract} from 'common/contract' export type ContractHighlightOptions = { contractIds?: string[] @@ -25,6 +26,7 @@ export function ContractsGrid(props: { hideQuickBet?: boolean hideGroupLink?: boolean noLinkAvatar?: boolean + showProbChange?: boolean } highlightOptions?: ContractHighlightOptions trackingPostfix?: string @@ -39,7 +41,8 @@ export function ContractsGrid(props: { highlightOptions, trackingPostfix, } = props - const { hideQuickBet, hideGroupLink, noLinkAvatar } = cardUIOptions || {} + const { hideQuickBet, hideGroupLink, noLinkAvatar, showProbChange } = + cardUIOptions || {} const { contractIds, highlightClassName } = highlightOptions || {} const onVisibilityUpdated = useCallback( (visible) => { @@ -73,24 +76,31 @@ export function ContractsGrid(props: { className="-ml-4 flex w-auto" columnClassName="pl-4 bg-clip-padding" > - {contracts.map((contract) => ( - <ContractCard - contract={contract} - key={contract.id} - showTime={showTime} - onClick={ - onContractClick ? () => onContractClick(contract) : undefined - } - noLinkAvatar={noLinkAvatar} - hideQuickBet={hideQuickBet} - hideGroupLink={hideGroupLink} - trackingPostfix={trackingPostfix} - className={clsx( - 'mb-4 break-inside-avoid-column overflow-hidden', // prevent content from wrapping (needs overflow on firefox) - contractIds?.includes(contract.id) && highlightClassName - )} - /> - ))} + {contracts.map((contract) => + showProbChange && contract.mechanism === 'cpmm-1' ? ( + <ContractCardProbChange + key={contract.id} + contract={contract as CPMMBinaryContract} + /> + ) : ( + <ContractCard + contract={contract} + key={contract.id} + showTime={showTime} + onClick={ + onContractClick ? () => onContractClick(contract) : undefined + } + noLinkAvatar={noLinkAvatar} + hideQuickBet={hideQuickBet} + hideGroupLink={hideGroupLink} + trackingPostfix={trackingPostfix} + className={clsx( + 'mb-4 break-inside-avoid-column overflow-hidden', // prevent content from wrapping (needs overflow on firefox) + contractIds?.includes(contract.id) && highlightClassName + )} + /> + ) + )} </Masonry> {loadMore && ( <VisibilityObserver diff --git a/web/components/contract/prob-change-table.tsx b/web/components/contract/prob-change-table.tsx index 0c7fdfbc..07b7c659 100644 --- a/web/components/contract/prob-change-table.tsx +++ b/web/components/contract/prob-change-table.tsx @@ -1,4 +1,5 @@ import clsx from 'clsx' +import { partition } from 'lodash' import { contractPath } from 'web/lib/firebase/contracts' import { CPMMContract } from 'common/contract' import { formatPercent } from 'common/util/format' @@ -8,16 +9,17 @@ import { Row } from '../layout/row' import { LoadingIndicator } from '../loading-indicator' export function ProbChangeTable(props: { - changes: - | { positiveChanges: CPMMContract[]; negativeChanges: CPMMContract[] } - | undefined + changes: CPMMContract[] | undefined full?: boolean }) { const { changes, full } = props if (!changes) return <LoadingIndicator /> - const { positiveChanges, negativeChanges } = changes + const [positiveChanges, negativeChanges] = partition( + changes, + (c) => c.probChanges.day > 0 + ) const threshold = 0.01 const positiveAboveThreshold = positiveChanges.filter( @@ -53,10 +55,18 @@ export function ProbChangeTable(props: { ) } -function ProbChangeRow(props: { contract: CPMMContract }) { - const { contract } = props +export function ProbChangeRow(props: { + contract: CPMMContract + className?: string +}) { + const { contract, className } = props return ( - <Row className="items-center justify-between gap-4 hover:bg-gray-100"> + <Row + className={clsx( + 'items-center justify-between gap-4 hover:bg-gray-100', + className + )} + > <SiteLink className="p-4 pr-0 font-semibold text-indigo-700" href={contractPath(contract)} diff --git a/web/hooks/use-contracts.ts b/web/hooks/use-contracts.ts index f2403a15..fb71ca60 100644 --- a/web/hooks/use-contracts.ts +++ b/web/hooks/use-contracts.ts @@ -11,10 +11,13 @@ import { trendingContractsQuery, getContractsQuery, } from 'web/lib/firebase/contracts' -import { QueryClient, useQueryClient } from 'react-query' +import { QueryClient, useQuery, useQueryClient } from 'react-query' import { MINUTE_MS } from 'common/util/time' import { query, limit } from 'firebase/firestore' import { Sort } from 'web/components/contract-search' +import { dailyScoreIndex } from 'web/lib/service/algolia' +import { CPMMBinaryContract } from 'common/contract' +import { zipObject } from 'lodash' export const useContracts = () => { const [contracts, setContracts] = useState<Contract[] | undefined>() @@ -26,6 +29,29 @@ export const useContracts = () => { return contracts } +export const useContractsByDailyScoreGroups = ( + groupSlugs: string[] | undefined +) => { + const facetFilters = ['isResolved:false'] + + const { data } = useQuery(['daily-score', groupSlugs], () => + Promise.all( + (groupSlugs ?? []).map((slug) => + dailyScoreIndex.search<CPMMBinaryContract>('', { + facetFilters: [...facetFilters, `groupLinks.slug:${slug}`], + }) + ) + ) + ) + if (!groupSlugs || !data || data.length !== groupSlugs.length) + return undefined + + return zipObject( + groupSlugs, + data.map((d) => d.hits.filter((c) => c.dailyScore)) + ) +} + const q = new QueryClient() export const getCachedContracts = async () => q.fetchQuery(['contracts'], () => listAllContracts(1000), { diff --git a/web/hooks/use-group.ts b/web/hooks/use-group.ts index 9bcb59cd..e918aa8c 100644 --- a/web/hooks/use-group.ts +++ b/web/hooks/use-group.ts @@ -104,7 +104,7 @@ export const useMemberGroupIds = (user: User | null | undefined) => { } export function useMemberGroupsSubscription(user: User | null | undefined) { - const cachedGroups = useMemberGroups(user?.id) ?? [] + const cachedGroups = useMemberGroups(user?.id) const [groups, setGroups] = useState(cachedGroups) const userId = user?.id diff --git a/web/hooks/use-prob-changes.tsx b/web/hooks/use-prob-changes.tsx index f3a6eee9..f2f3ce13 100644 --- a/web/hooks/use-prob-changes.tsx +++ b/web/hooks/use-prob-changes.tsx @@ -1,75 +1,47 @@ -import { useFirestoreQueryData } from '@react-query-firebase/firestore' -import { CPMMContract } from 'common/contract' -import { MINUTE_MS } from 'common/util/time' -import { useQuery, useQueryClient } from 'react-query' +import { CPMMBinaryContract } from 'common/contract' +import { sortBy, uniqBy } from 'lodash' +import { useQuery } from 'react-query' import { - getProbChangesNegative, - getProbChangesPositive, -} from 'web/lib/firebase/contracts' -import { getValues } from 'web/lib/firebase/utils' -import { getIndexName, searchClient } from 'web/lib/service/algolia' + probChangeAscendingIndex, + probChangeDescendingIndex, +} from 'web/lib/service/algolia' -export const useProbChangesAlgolia = (userId: string) => { - const { data: positiveData } = useQuery(['prob-change-day', userId], () => - searchClient - .initIndex(getIndexName('prob-change-day')) - .search<CPMMContract>('', { - facetFilters: ['uniqueBettorIds:' + userId, 'isResolved:false'], - }) - ) - const { data: negativeData } = useQuery( - ['prob-change-day-ascending', userId], - () => - searchClient - .initIndex(getIndexName('prob-change-day-ascending')) - .search<CPMMContract>('', { - facetFilters: ['uniqueBettorIds:' + userId, 'isResolved:false'], - }) - ) +export const useProbChanges = ( + filters: { bettorId?: string; groupSlugs?: string[] } = {} +) => { + const { bettorId, groupSlugs } = filters - if (!positiveData || !negativeData) { - return undefined + const bettorFilter = bettorId ? `uniqueBettorIds:${bettorId}` : '' + const groupFilters = groupSlugs + ? groupSlugs.map((slug) => `groupLinks.slug:${slug}`) + : [] + + const facetFilters = [ + 'isResolved:false', + 'outcomeType:BINARY', + bettorFilter, + groupFilters, + ] + const searchParams = { + facetFilters, + hitsPerPage: 50, } - return { - positiveChanges: positiveData.hits - .filter((c) => c.probChanges && c.probChanges.day > 0) - .filter((c) => c.outcomeType === 'BINARY'), - negativeChanges: negativeData.hits - .filter((c) => c.probChanges && c.probChanges.day < 0) - .filter((c) => c.outcomeType === 'BINARY'), - } -} - -export const useProbChanges = (userId: string) => { - const { data: positiveChanges } = useFirestoreQueryData( - ['prob-changes-day-positive', userId], - getProbChangesPositive(userId) - ) - const { data: negativeChanges } = useFirestoreQueryData( - ['prob-changes-day-negative', userId], - getProbChangesNegative(userId) - ) - - if (!positiveChanges || !negativeChanges) { - return undefined - } - - return { positiveChanges, negativeChanges } -} - -export const usePrefetchProbChanges = (userId: string | undefined) => { - const queryClient = useQueryClient() - if (userId) { - queryClient.prefetchQuery( - ['prob-changes-day-positive', userId], - () => getValues(getProbChangesPositive(userId)), - { staleTime: MINUTE_MS } - ) - queryClient.prefetchQuery( - ['prob-changes-day-negative', userId], - () => getValues(getProbChangesNegative(userId)), - { staleTime: MINUTE_MS } - ) - } + const { data: positiveChanges } = useQuery( + ['prob-change-day', groupSlugs], + () => probChangeDescendingIndex.search<CPMMBinaryContract>('', searchParams) + ) + const { data: negativeChanges } = useQuery( + ['prob-change-day-ascending', groupSlugs], + () => probChangeAscendingIndex.search<CPMMBinaryContract>('', searchParams) + ) + + if (!positiveChanges || !negativeChanges) return undefined + + const hits = uniqBy( + [...positiveChanges.hits, ...negativeChanges.hits], + (c) => c.id + ) + + return sortBy(hits, (c) => Math.abs(c.probChanges.day)).reverse() } diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts index 33f6533b..927f7187 100644 --- a/web/lib/firebase/contracts.ts +++ b/web/lib/firebase/contracts.ts @@ -16,7 +16,7 @@ import { import { partition, sortBy, sum, uniqBy } from 'lodash' import { coll, getValues, listenForValue, listenForValues } from './utils' -import { BinaryContract, Contract, CPMMContract } from 'common/contract' +import { BinaryContract, Contract } from 'common/contract' import { chooseRandomSubset } from 'common/util/random' import { formatMoney, formatPercent } from 'common/util/format' import { DAY_MS } from 'common/util/time' @@ -426,21 +426,3 @@ export async function getRecentBetsAndComments(contract: Contract) { recentComments, } } - -export const getProbChangesPositive = (userId: string) => - query( - contracts, - where('uniqueBettorIds', 'array-contains', userId), - where('probChanges.day', '>', 0), - orderBy('probChanges.day', 'desc'), - limit(10) - ) as Query<CPMMContract> - -export const getProbChangesNegative = (userId: string) => - query( - contracts, - where('uniqueBettorIds', 'array-contains', userId), - where('probChanges.day', '<', 0), - orderBy('probChanges.day', 'asc'), - limit(10) - ) as Query<CPMMContract> diff --git a/web/lib/service/algolia.ts b/web/lib/service/algolia.ts index 3b6648a1..29cbd6bf 100644 --- a/web/lib/service/algolia.ts +++ b/web/lib/service/algolia.ts @@ -13,3 +13,13 @@ export const searchIndexName = export const getIndexName = (sort: string) => { return `${indexPrefix}contracts-${sort}` } + +export const probChangeDescendingIndex = searchClient.initIndex( + getIndexName('prob-change-day') +) +export const probChangeAscendingIndex = searchClient.initIndex( + getIndexName('prob-change-day-ascending') +) +export const dailyScoreIndex = searchClient.initIndex( + getIndexName('daily-score') +) diff --git a/web/pages/daily-movers.tsx b/web/pages/daily-movers.tsx index 3b709d89..0a17e9e2 100644 --- a/web/pages/daily-movers.tsx +++ b/web/pages/daily-movers.tsx @@ -2,14 +2,17 @@ import { ProbChangeTable } from 'web/components/contract/prob-change-table' import { Col } from 'web/components/layout/col' import { Page } from 'web/components/page' import { Title } from 'web/components/title' -import { useProbChangesAlgolia } from 'web/hooks/use-prob-changes' +import { useProbChanges } from 'web/hooks/use-prob-changes' import { useTracking } from 'web/hooks/use-tracking' import { useUser } from 'web/hooks/use-user' export default function DailyMovers() { const user = useUser() + const bettorId = user?.id ?? undefined - const changes = useProbChangesAlgolia(user?.id ?? '') + const changes = useProbChanges({ bettorId })?.filter( + (c) => Math.abs(c.probChanges.day) >= 0.01 + ) useTracking('view daily movers') diff --git a/web/pages/home/edit.tsx b/web/pages/home/edit.tsx index 48e10c6c..8c5f8ab5 100644 --- a/web/pages/home/edit.tsx +++ b/web/pages/home/edit.tsx @@ -28,7 +28,7 @@ export default function Home() { } const groups = useMemberGroupsSubscription(user) - const { sections } = getHomeItems(groups, homeSections) + const { sections } = getHomeItems(groups ?? [], homeSections) return ( <Page> diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index 83bcb15b..f13fc200 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -8,6 +8,7 @@ import { import { PlusCircleIcon, XCircleIcon } from '@heroicons/react/outline' import clsx from 'clsx' import { toast, Toaster } from 'react-hot-toast' +import { Dictionary } from 'lodash' import { Page } from 'web/components/page' import { Col } from 'web/components/layout/col' @@ -31,11 +32,10 @@ import { ProbChangeTable } from 'web/components/contract/prob-change-table' import { groupPath, joinGroup, leaveGroup } from 'web/lib/firebase/groups' import { usePortfolioHistory } from 'web/hooks/use-portfolio-history' import { formatMoney } from 'common/util/format' -import { useProbChangesAlgolia } from 'web/hooks/use-prob-changes' +import { useProbChanges } from 'web/hooks/use-prob-changes' import { ProfitBadge } from 'web/components/bets-list' import { calculatePortfolioProfit } from 'common/calculate-metrics' import { hasCompletedStreakToday } from 'web/components/profile/betting-streak-modal' -import { useContractsQuery } from 'web/hooks/use-contracts' import { ContractsGrid } from 'web/components/contract/contracts-grid' import { PillButton } from 'web/components/buttons/pill-button' import { filterDefined } from 'common/util/array' @@ -43,6 +43,8 @@ import { updateUser } from 'web/lib/firebase/users' import { isArray, keyBy } from 'lodash' import { usePrefetch } from 'web/hooks/use-prefetch' import { Title } from 'web/components/title' +import { CPMMBinaryContract } from 'common/contract' +import { useContractsByDailyScoreGroups } from 'web/hooks/use-contracts' export default function Home() { const user = useUser() @@ -54,20 +56,19 @@ export default function Home() { const groups = useMemberGroupsSubscription(user) - const { sections } = getHomeItems(groups, user?.homeSections ?? []) + const { sections } = getHomeItems(groups ?? [], user?.homeSections ?? []) useEffect(() => { - if ( - user && - !user.homeSections && - sections.length > 0 && - groups.length > 0 - ) { + if (user && !user.homeSections && sections.length > 0 && groups) { // Save initial home sections. updateUser(user.id, { homeSections: sections.map((s) => s.id) }) } }, [user, sections, groups]) + const groupContracts = useContractsByDailyScoreGroups( + groups?.map((g) => g.slug) + ) + return ( <Page> <Toaster /> @@ -81,9 +82,13 @@ export default function Home() { <DailyStats user={user} /> </Row> - {sections.map((section) => renderSection(section, user, groups))} + <> + {sections.map((section) => + renderSection(section, user, groups, groupContracts) + )} - <TrendingGroupsSection user={user} /> + <TrendingGroupsSection user={user} /> + </> </Col> <button type="button" @@ -134,7 +139,8 @@ export const getHomeItems = (groups: Group[], sections: string[]) => { function renderSection( section: { id: string; label: string }, user: User | null | undefined, - groups: Group[] + groups: Group[] | undefined, + groupContracts: Dictionary<CPMMBinaryContract[]> | undefined ) { const { id, label } = section if (id === 'daily-movers') { @@ -156,8 +162,23 @@ function renderSection( <SearchSection key={id} label={label} sort={sort.value} user={user} /> ) - const group = groups.find((g) => g.id === id) - if (group) return <GroupSection key={id} group={group} user={user} /> + if (groups && groupContracts) { + const group = groups.find((g) => g.id === id) + if (group) { + const contracts = groupContracts[group.slug].filter( + (c) => Math.abs(c.probChanges.day) >= 0.01 + ) + if (contracts.length === 0) return null + return ( + <GroupSection + key={id} + group={group} + user={user} + contracts={contracts} + /> + ) + } + } return null } @@ -207,7 +228,6 @@ function SearchSection(props: { defaultPill={pill} noControls maxResults={6} - headerClassName="sticky" persistPrefix={`home-${sort}`} /> </Col> @@ -217,10 +237,9 @@ function SearchSection(props: { function GroupSection(props: { group: Group user: User | null | undefined | undefined + contracts: CPMMBinaryContract[] }) { - const { group, user } = props - - const contracts = useContractsQuery('score', 4, { groupSlug: group.slug }) + const { group, user, contracts } = props return ( <Col> @@ -245,22 +264,22 @@ function GroupSection(props: { <XCircleIcon className={'h-5 w-5 flex-shrink-0'} aria-hidden="true" /> </Button> </SectionHeader> - <ContractsGrid contracts={contracts} /> + <ContractsGrid + contracts={contracts.slice(0, 4)} + cardUIOptions={{ showProbChange: true }} + /> </Col> ) } function DailyMoversSection(props: { userId: string | null | undefined }) { const { userId } = props - const changes = useProbChangesAlgolia(userId ?? '') + const changes = useProbChanges({ bettorId: userId ?? undefined })?.filter( + (c) => Math.abs(c.probChanges.day) >= 0.01 + ) - if (changes) { - const { positiveChanges, negativeChanges } = changes - if ( - !positiveChanges.find((c) => c.probChanges.day >= 0.01) || - !negativeChanges.find((c) => c.probChanges.day <= -0.01) - ) - return null + if (changes && changes.length === 0) { + return null } return ( @@ -332,6 +351,10 @@ export function TrendingGroupsSection(props: { const count = full ? 100 : 25 const chosenGroups = groups.slice(0, count) + if (chosenGroups.length === 0) { + return null + } + return ( <Col className={className}> <SectionHeader label="Trending groups" href="/explore-groups"> From 70bc5b2c4aa9642cc86bcfe79b053e3348cfc8ab Mon Sep 17 00:00:00 2001 From: jahooma <jahooma@users.noreply.github.com> Date: Thu, 22 Sep 2022 21:58:40 +0000 Subject: [PATCH 24/60] Auto-prettification --- web/components/contract/contracts-grid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/components/contract/contracts-grid.tsx b/web/components/contract/contracts-grid.tsx index 4f573fb8..0b93148d 100644 --- a/web/components/contract/contracts-grid.tsx +++ b/web/components/contract/contracts-grid.tsx @@ -10,7 +10,7 @@ import clsx from 'clsx' import { LoadingIndicator } from '../loading-indicator' import { VisibilityObserver } from '../visibility-observer' import Masonry from 'react-masonry-css' -import { CPMMBinaryContract} from 'common/contract' +import { CPMMBinaryContract } from 'common/contract' export type ContractHighlightOptions = { contractIds?: string[] From 08202c3edede25652c3f69a12c91ee4f7260fa7b Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Fri, 23 Sep 2022 10:02:40 -0400 Subject: [PATCH 25/60] Add close market endpoint --- functions/src/close-market.ts | 50 +++++++++++++++++++++++++++ functions/src/index.ts | 6 +++- web/next.config.js | 3 ++ web/pages/api/v0/market/[id]/close.ts | 28 +++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 functions/src/close-market.ts create mode 100644 web/pages/api/v0/market/[id]/close.ts diff --git a/functions/src/close-market.ts b/functions/src/close-market.ts new file mode 100644 index 00000000..86d73107 --- /dev/null +++ b/functions/src/close-market.ts @@ -0,0 +1,50 @@ +import * as admin from 'firebase-admin' +import { z } from 'zod' + +import { Contract } from '../../common/contract' +import { getUser } from './utils' + +import { isAdmin, isManifoldId } from '../../common/envs/constants' +import { APIError, newEndpoint, validate } from './api' + +const bodySchema = z.object({ + contractId: z.string(), +}) + +export const closemarket = newEndpoint({}, async (req, auth) => { + const { contractId } = validate(bodySchema, req.body) + const contractDoc = firestore.doc(`contracts/${contractId}`) + const contractSnap = await contractDoc.get() + if (!contractSnap.exists) + throw new APIError(404, 'No contract exists with the provided ID') + const contract = contractSnap.data() as Contract + const { creatorId, closeTime } = contract + const firebaseUser = await admin.auth().getUser(auth.uid) + + if ( + creatorId !== auth.uid && + !isManifoldId(auth.uid) && + !isAdmin(firebaseUser.email) + ) + throw new APIError(403, 'User is not creator of contract') + + const now = Date.now() + if (closeTime && closeTime < now) + throw new APIError(400, 'Contract already closed') + + const creator = await getUser(creatorId) + if (!creator) throw new APIError(500, 'Creator not found') + + const updatedContract = { + ...contract, + closeTime: now, + } + + await contractDoc.update(updatedContract) + + console.log('contract ', contractId, 'closed') + + return updatedContract +}) + +const firestore = admin.firestore() diff --git a/functions/src/index.ts b/functions/src/index.ts index adfee75e..2cb6f515 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -50,6 +50,7 @@ export * from './resolve-market' export * from './unsubscribe' export * from './stripe' export * from './mana-bonus-email' +export * from './close-market' import { health } from './health' import { transact } from './transact' @@ -66,6 +67,7 @@ import { addliquidity } from './add-liquidity' import { withdrawliquidity } from './withdraw-liquidity' import { creategroup } from './create-group' import { resolvemarket } from './resolve-market' +import { closemarket } from './close-market' import { unsubscribe } from './unsubscribe' import { stripewebhook, createcheckoutsession } from './stripe' import { getcurrentuser } from './get-current-user' @@ -91,6 +93,7 @@ const addLiquidityFunction = toCloudFunction(addliquidity) const withdrawLiquidityFunction = toCloudFunction(withdrawliquidity) const createGroupFunction = toCloudFunction(creategroup) const resolveMarketFunction = toCloudFunction(resolvemarket) +const closeMarketFunction = toCloudFunction(closemarket) const unsubscribeFunction = toCloudFunction(unsubscribe) const stripeWebhookFunction = toCloudFunction(stripewebhook) const createCheckoutSessionFunction = toCloudFunction(createcheckoutsession) @@ -115,11 +118,12 @@ export { withdrawLiquidityFunction as withdrawliquidity, createGroupFunction as creategroup, resolveMarketFunction as resolvemarket, + closeMarketFunction as closemarket, unsubscribeFunction as unsubscribe, stripeWebhookFunction as stripewebhook, createCheckoutSessionFunction as createcheckoutsession, getCurrentUserFunction as getcurrentuser, acceptChallenge as acceptchallenge, createPostFunction as createpost, - saveTwitchCredentials as savetwitchcredentials + saveTwitchCredentials as savetwitchcredentials, } diff --git a/web/next.config.js b/web/next.config.js index cf727fd4..21b375ba 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -9,6 +9,9 @@ module.exports = { reactStrictMode: true, optimizeFonts: false, experimental: { + images: { + allowFutureImage: true, + }, scrollRestoration: true, externalDir: true, modularizeImports: { diff --git a/web/pages/api/v0/market/[id]/close.ts b/web/pages/api/v0/market/[id]/close.ts new file mode 100644 index 00000000..d1c9ac5e --- /dev/null +++ b/web/pages/api/v0/market/[id]/close.ts @@ -0,0 +1,28 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import { + CORS_ORIGIN_MANIFOLD, + CORS_ORIGIN_LOCALHOST, +} from 'common/envs/constants' +import { applyCorsHeaders } from 'web/lib/api/cors' +import { fetchBackend, forwardResponse } from 'web/lib/api/proxy' + +export const config = { api: { bodyParser: true } } + +export default async function route(req: NextApiRequest, res: NextApiResponse) { + await applyCorsHeaders(req, res, { + origin: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_LOCALHOST], + methods: 'POST', + }) + + const { id } = req.query + const contractId = id as string + + if (req.body) req.body.contractId = contractId + try { + const backendRes = await fetchBackend(req, 'closemarket') + await forwardResponse(res, backendRes) + } catch (err) { + console.error('Error talking to cloud function: ', err) + res.status(500).json({ message: 'Error communicating with backend.' }) + } +} From 91f89ccb3de3dc4d162e6321eab71a135e490c1c Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Fri, 23 Sep 2022 10:14:41 -0400 Subject: [PATCH 26/60] Add docs fo /close, allow to pass closeTime --- docs/docs/api.md | 8 ++++++++ functions/src/close-market.ts | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/docs/docs/api.md b/docs/docs/api.md index 64e26de8..986654a4 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -582,6 +582,14 @@ $ curl https://manifold.markets/api/v0/market -X POST -H 'Content-Type: applicat "initialProb":25}' ``` + +### `POST /v0/market/[marketId]/close` + +Closes a market on behalf of the authorized user. +- `contractId`: Required. The id of the market to close. +- `closeTime`: Optional. Milliseconds since the epoch to close the market at. If not provided, the market will be closed immediately. Cannot provide close time in past. + + ### `POST /v0/market/[marketId]/resolve` Resolves a market on behalf of the authorized user. diff --git a/functions/src/close-market.ts b/functions/src/close-market.ts index 86d73107..b8b252a7 100644 --- a/functions/src/close-market.ts +++ b/functions/src/close-market.ts @@ -9,16 +9,17 @@ import { APIError, newEndpoint, validate } from './api' const bodySchema = z.object({ contractId: z.string(), + closeTime: z.number().int().nonnegative().optional(), }) export const closemarket = newEndpoint({}, async (req, auth) => { - const { contractId } = validate(bodySchema, req.body) + const { contractId, closeTime } = validate(bodySchema, req.body) const contractDoc = firestore.doc(`contracts/${contractId}`) const contractSnap = await contractDoc.get() if (!contractSnap.exists) throw new APIError(404, 'No contract exists with the provided ID') const contract = contractSnap.data() as Contract - const { creatorId, closeTime } = contract + const { creatorId } = contract const firebaseUser = await admin.auth().getUser(auth.uid) if ( @@ -29,15 +30,22 @@ export const closemarket = newEndpoint({}, async (req, auth) => { throw new APIError(403, 'User is not creator of contract') const now = Date.now() - if (closeTime && closeTime < now) + if (!closeTime && contract.closeTime && contract.closeTime < now) throw new APIError(400, 'Contract already closed') + if (closeTime && closeTime < now) + throw new APIError( + 400, + 'Close time must be in the future. ' + + 'Alternatively, do not provide a close time to close immediately.' + ) + const creator = await getUser(creatorId) if (!creator) throw new APIError(500, 'Creator not found') const updatedContract = { ...contract, - closeTime: now, + closeTime: closeTime ? closeTime : now, } await contractDoc.update(updatedContract) From 54839555903ea1a81a32b5026bda9b6fa6b6436c Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Fri, 23 Sep 2022 10:21:11 -0400 Subject: [PATCH 27/60] Remove contractId from required JSON for /close --- docs/docs/api.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/docs/api.md b/docs/docs/api.md index 986654a4..007f6fa6 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -586,7 +586,6 @@ $ curl https://manifold.markets/api/v0/market -X POST -H 'Content-Type: applicat ### `POST /v0/market/[marketId]/close` Closes a market on behalf of the authorized user. -- `contractId`: Required. The id of the market to close. - `closeTime`: Optional. Milliseconds since the epoch to close the market at. If not provided, the market will be closed immediately. Cannot provide close time in past. From 47c97c36db33d1ac3394a3d1aad5d19b95710f4e Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Fri, 23 Sep 2022 12:01:31 -0400 Subject: [PATCH 28/60] Add Alignment Markets to Awesome Manifold --- docs/docs/awesome-manifold.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/docs/awesome-manifold.md b/docs/docs/awesome-manifold.md index 7a30fed6..066193d3 100644 --- a/docs/docs/awesome-manifold.md +++ b/docs/docs/awesome-manifold.md @@ -11,6 +11,7 @@ A list of community-created projects built on, or related to, Manifold Markets. - [CivicDashboard](https://civicdash.org/dashboard) - Uses Manifold to for tracked solutions for the SF city government - [Research.Bet](https://research.bet/) - Prediction market for scientific papers, using Manifold - [WagerWith.me](https://www.wagerwith.me/) — Bet with your friends, with full Manifold integration to bet with M$. +- [Alignment Markets](https://alignmentmarkets.com/) - Bet on the progress of benchmarks in ML safety! ## API / Dev @@ -28,6 +29,7 @@ A list of community-created projects built on, or related to, Manifold Markets. - [mana](https://github.com/AnnikaCodes/mana) - A Discord bot for Manifold by [@arae](https://manifold.markets/arae) ## Writeups + - [Information Markets, Decision Markets, Attention Markets, Action Markets](https://astralcodexten.substack.com/p/information-markets-decision-markets) by Scott Alexander - [Mismatched Monetary Motivation in Manifold Markets](https://kevin.zielnicki.com/2022/02/17/manifold/) by Kevin Zielnicki - [Introducing the Salem/CSPI Forecasting Tournament](https://www.cspicenter.com/p/introducing-the-salemcspi-forecasting) by Richard Hanania @@ -36,5 +38,5 @@ A list of community-created projects built on, or related to, Manifold Markets. ## Art -- Folded origami and doodles by [@hamnox](https://manifold.markets/hamnox) ![](https://i.imgur.com/nVGY4pL.png) -- Laser-cut Foldy by [@wasabipesto](https://manifold.markets/wasabipesto) ![](https://i.imgur.com/g9S6v3P.jpg) +- Folded origami and doodles by [@hamnox](https://manifold.markets/hamnox) ![](https://i.imgur.com/nVGY4pL.png) +- Laser-cut Foldy by [@wasabipesto](https://manifold.markets/wasabipesto) ![](https://i.imgur.com/g9S6v3P.jpg) From 61a9224a7d36e8b9f65a3a2739faf4aeb53015fe Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Fri, 23 Sep 2022 12:10:48 -0400 Subject: [PATCH 29/60] Move Civid Dashboard and Research.Bet to Alumni --- docs/docs/awesome-manifold.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/docs/awesome-manifold.md b/docs/docs/awesome-manifold.md index 066193d3..ed01f75c 100644 --- a/docs/docs/awesome-manifold.md +++ b/docs/docs/awesome-manifold.md @@ -8,8 +8,6 @@ A list of community-created projects built on, or related to, Manifold Markets. ## Sites using Manifold -- [CivicDashboard](https://civicdash.org/dashboard) - Uses Manifold to for tracked solutions for the SF city government -- [Research.Bet](https://research.bet/) - Prediction market for scientific papers, using Manifold - [WagerWith.me](https://www.wagerwith.me/) — Bet with your friends, with full Manifold integration to bet with M$. - [Alignment Markets](https://alignmentmarkets.com/) - Bet on the progress of benchmarks in ML safety! @@ -40,3 +38,10 @@ A list of community-created projects built on, or related to, Manifold Markets. - Folded origami and doodles by [@hamnox](https://manifold.markets/hamnox) ![](https://i.imgur.com/nVGY4pL.png) - Laser-cut Foldy by [@wasabipesto](https://manifold.markets/wasabipesto) ![](https://i.imgur.com/g9S6v3P.jpg) + +## Alumni + +_These projects are no longer active, but were really really cool!_ + +- [Research.Bet](https://research.bet/) - Prediction market for scientific papers, using Manifold +- [CivicDashboard](https://civicdash.org/dashboard) - Uses Manifold to for tracked solutions for the SF city government From ebcecd4fe93fb2d65cff10b0f3bbe9aab19b0afe Mon Sep 17 00:00:00 2001 From: Sinclair Chen <abc.sinclair@gmail.com> Date: Fri, 23 Sep 2022 15:01:25 -0400 Subject: [PATCH 30/60] remove unused files --- web/public/praying-mantis-light.svg | 67 ----------------------- web/public/world-trading-background.webp | Bin 272522 -> 0 bytes web/tailwind.config.js | 3 - 3 files changed, 70 deletions(-) delete mode 100644 web/public/praying-mantis-light.svg delete mode 100644 web/public/world-trading-background.webp diff --git a/web/public/praying-mantis-light.svg b/web/public/praying-mantis-light.svg deleted file mode 100644 index cc82cd53..00000000 --- a/web/public/praying-mantis-light.svg +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - version="1.1" - id="svg2" - xml:space="preserve" - width="2829.3333" - height="2829.3333" - viewBox="0 0 2829.3333 2829.3333" - sodipodi:docname="shutterstock_2073140717.eps"><metadata - id="metadata8"><rdf:RDF><cc:Work - rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs - id="defs6" /><sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="640" - inkscape:window-height="480" - id="namedview4" /><g - id="g10" - inkscape:groupmode="layer" - inkscape:label="ink_ext_XXXXXX" - transform="matrix(1.3333333,0,0,-1.3333333,0,2829.3333)"><g - id="g12" - transform="scale(0.1)"><path - d="m 10622.5,11248.2 c -81.6,-54.3 -178.4,-122.5 -292.3,-197.1 -114.1,-74.3 -241.9,-159.2 -384.07,-247.8 -140.7,-90.6 -296.56,-183.4 -460.04,-283.5 -81.17,-50.9 -167.57,-98.4 -254.29,-149.2 -87.66,-49.5 -174.65,-104.3 -266.68,-153.9 -91.29,-50.7 -184.14,-102.4 -278.09,-154.6 -93.94,-52.3 -191.33,-100.9 -287.65,-153.3 -192.27,-105.6 -393.64,-201 -592.62,-301 -99.96,-49 -201.33,-94.9 -301.6,-142.3 -100.32,-47.3 -200.08,-94.8 -301.41,-136.4 -100.82,-42.9 -200.55,-86.1 -298.87,-129.4 -98.47,-42.8 -198.16,-79 -294.96,-118 -97.38,-37.3 -191.91,-77.8 -286.76,-110.5 -94.68,-33.6 -187.3,-66.4 -277.42,-98.3 -45.11,-15.9 -89.61,-31.7 -133.44,-47.3 -44.37,-13.7 -88.12,-27.1 -131.09,-40.4 -86.05,-26.7 -169.14,-52.4 -248.91,-77.2 -39.96,-12.3 -79.06,-24.4 -117.3,-36.2 -38.71,-9.8 -76.56,-19.5 -113.44,-28.9 -73.75,-19.2 -143.71,-37.5 -209.45,-54.6 -65.9,-16.6 -127.23,-34.6 -184.73,-46.9 -57.61,-11.8 -110.58,-22.6 -158.43,-32.4 -191.41,-40.4 -300.86,-63.6 -301.14,-63.6 0.2,0 111.49,12.4 306.1,34.2 48.79,5.8 102.77,12.2 161.6,19.2 58.83,7.2 121.13,21.7 188.51,33.5 67.27,12.6 138.87,26.1 214.34,40.3 37.73,7.3 76.44,14.7 116.05,22.4 39.11,9.8 79.11,19.8 119.97,29.9 81.75,20.6 166.87,42 255.03,64.2 44.07,11.2 88.95,22.5 134.18,35 44.77,13.9 90.28,28.1 136.37,42.4 92.31,28.7 187.07,58.2 283.99,88.3 48.78,14.2 96.99,31.6 145.43,49.7 48.63,17.8 97.69,35.8 147.18,53.9 98.64,37.1 200.35,71.4 300.78,112.2 100.47,40.8 201.92,82.9 303.87,125.8 102.74,41.4 203.75,88.5 305.43,135.4 101.49,47.1 204.38,92.5 305.51,141.4 200,102.5 402.34,200.4 595.35,308.4 195.7,103 382.34,214.9 563.79,321.6 91.25,52.3 178.28,108.5 264.06,162.3 85.31,54.6 170.2,105.7 249.92,160 80.24,53.6 158.25,105.6 233.75,155.9 75.39,50.4 145.9,102.7 214.81,150.9 138.27,95.7 260.57,190 369.47,272.5 109.4,81.8 200.6,159.2 277.3,220.1 76,61.8 132.8,113.9 172.9,147.7 39.7,34.4 60.8,52.8 60.8,52.8 0,0 -91.6,-64.5 -251.8,-177.2" - style="fill:#668a29;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path14" /><path - d="m 15228.8,15825 c -102.2,-173.3 -176.3,-358 -218.3,-550.5 -19.6,-17.6 -37.4,-37 -53.4,-58 -163.6,59.3 -342.5,63.1 -484.2,31 54.1,715.2 441.9,1360.2 1047.5,1839.3 653.8,517 1560.1,838.1 2563.2,838 v 99.8 c -1024.4,-0.1 -1951.8,-327.4 -2625.1,-859.5 -610.2,-482.2 -1010.9,-1135.1 -1080.6,-1863.1 24.7,-17.7 47.3,-38.1 67.4,-60.7 64.3,-72.4 103.6,-167.4 103.6,-271.7 0,-169.6 -103,-315.2 -250,-377.3 -49.1,-20.7 -102.9,-32.2 -159.4,-32.2 -188.5,0 -346.9,127.6 -394.5,301 -361.9,-310.9 -784.7,-754 -1230.9,-1104.8 -123.3,-97 -259.3,-238.4 -399.4,-403.4 -69.3,-51.5 -131.7,-122.5 -178.1,-219.4 -456.2,-583.6 -916.7,-1325.1 -1094.3,-1547.3 -457.6,-216.4 -911.4,-311.1 -1384.14,-404.1 -205.43,-40.3 -414.41,-80.5 -628.86,-130 -130.39,-30.2 -262.89,-64.1 -397.74,-103.4 -167.58,-48.9 -338.83,-106.5 -514.76,-177.3 -199.85,-80.5 -405.55,-177.8 -618.36,-298.2 -39.92,-22.7 -78.24,-45.2 -117.42,-67.8 -174.61,-100.7 -341.76,-201.1 -501.61,-300.9 C 6201.64,9806 5787.19,9513.4 5425,9237.8 c -215.78,-164.2 -413.55,-322.4 -595.2,-472.1 -135.85,-111.9 -262.73,-218.9 -381.99,-320.3 0.28,0 109.73,23.2 301.14,63.6 47.85,9.8 100.82,20.6 158.43,32.4 57.5,12.3 118.83,30.3 184.73,46.9 65.74,17.1 135.7,35.4 209.45,54.6 36.88,9.4 74.73,19.1 113.44,28.9 38.24,11.8 77.34,23.9 117.3,36.2 79.77,24.8 162.86,50.5 248.91,77.2 42.97,13.3 86.72,26.7 131.09,40.4 43.83,15.6 88.33,31.4 133.44,47.3 90.12,31.9 182.74,64.7 277.42,98.3 94.85,32.7 189.38,73.2 286.76,110.5 96.8,39 196.49,75.2 294.96,118 98.32,43.3 198.05,86.5 298.87,129.4 101.33,41.6 201.09,89.1 301.41,136.4 100.27,47.4 201.64,93.3 301.6,142.3 198.98,100 400.35,195.4 592.62,301 96.32,52.4 193.71,101 287.65,153.3 93.95,52.2 186.8,103.9 278.09,154.6 92.03,49.6 179.02,104.4 266.68,153.9 86.72,50.8 173.12,98.3 254.29,149.2 163.48,100.1 319.34,192.9 460.04,283.5 142.17,88.6 269.97,173.5 384.07,247.8 113.9,74.6 210.7,142.8 292.3,197.1 160.2,112.7 251.8,177.2 251.8,177.2 0,0 -21.1,-18.4 -60.8,-52.8 -40.1,-33.8 -96.9,-85.9 -172.9,-147.7 -76.7,-60.9 -167.9,-138.3 -277.3,-220.1 -108.9,-82.5 -231.2,-176.8 -369.47,-272.5 -68.91,-48.2 -139.42,-100.5 -214.81,-150.9 -75.5,-50.3 -153.51,-102.3 -233.75,-155.9 -79.72,-54.3 -164.61,-105.4 -249.92,-160 -85.78,-53.8 -172.81,-110 -264.06,-162.3 -181.45,-106.7 -368.09,-218.6 -563.79,-321.6 -193.01,-108 -395.35,-205.9 -595.35,-308.4 -101.13,-48.9 -204.02,-94.3 -305.51,-141.4 -101.68,-46.9 -202.69,-94 -305.43,-135.4 -101.95,-42.9 -203.4,-85 -303.87,-125.8 -100.43,-40.8 -202.14,-75.1 -300.78,-112.2 -49.49,-18.1 -98.55,-36.1 -147.18,-53.9 -48.44,-18.1 -96.65,-35.5 -145.43,-49.7 -96.92,-30.1 -191.68,-59.6 -283.99,-88.3 -46.09,-14.3 -91.6,-28.5 -136.37,-42.4 -45.23,-12.5 -90.11,-23.8 -134.18,-35 -88.16,-22.2 -173.28,-43.6 -255.03,-64.2 -40.86,-10.1 -80.86,-20.1 -119.97,-29.9 -39.61,-7.7 -78.32,-15.1 -116.05,-22.4 -75.47,-14.2 -147.07,-27.7 -214.34,-40.3 -67.38,-11.8 -129.68,-26.3 -188.51,-33.5 -58.83,-7 -112.81,-13.4 -161.6,-19.2 -194.61,-21.8 -305.9,-34.2 -306.1,-34.2 -663.4,-564.2 -1086.87,-950 -1454.8,-983.5 72.89,-128.8 730.04,15.1 1664.29,339.7 141.8,49.3 289.85,102.7 443.36,160 51.41,19.1 103.44,38.8 156.02,58.8 52.23,-252.7 180.66,-592.2 394.45,-911.7 142.27,-212.7 291.06,-397.8 427.27,-538.4 l -3.79,-2.3 C 5872.3,6432.5 3914.65,3342.3 4005.23,3206.8 c 90.63,-135.4 2195.32,2735.1 2397.7,2870.4 202.34,135.4 292.97,354.9 202.3,490.5 -12.93,19.3 -29.18,35.6 -47.61,49.4 -63.56,215.9 -210.74,513.2 -415.86,819.8 -123.63,184.9 -164.26,536.4 -199.73,855.9 569.34,235 1177.93,507.5 1784.73,805.2 87.85,-408.4 251.83,-803.5 371.33,-959.7 97.34,-159.8 600.11,-435.7 1207.54,-515.4 253.75,-33.3 490.97,-43.5 686.6,-33.8 l -0.75,-4.3 c -31.64,-241.4 1000.52,-3751 1162.12,-3772.2 161.7,-21.2 -608.5,3453.9 -576.8,3695.4 31.7,241.3 -73.7,454.2 -235.3,475.4 -23.1,3.1 -46,1.6 -68.6,-3.1 -204.1,94.5 -524.66,179.9 -890.44,227.9 -242.62,31.8 -570.78,272.4 -853.59,468.9 40.08,153.4 74.26,327.7 98.67,514 17.73,135 28.87,265.3 33.98,387.3 141.41,76.3 281.53,153.6 419.73,231.8 190.35,107.7 373.91,215.7 551.95,323.5 148.87,90.2 293.4,180.2 433.4,269.7 798.4,510.8 1451.5,1007.5 1939,1436.7 86.8,-272.8 194.7,-506.2 280,-617.7 97.3,-159.7 600.1,-435.6 1207.6,-515.3 253.7,-33.4 490.9,-43.5 686.6,-33.8 l -0.8,-4.4 c -31.7,-241.4 1000.5,-3750.9 1162.2,-3772.1 161.6,-21.2 -608.6,3453.9 -576.9,3695.3 31.7,241.4 -73.7,454.3 -235.3,475.5 -23.1,3 -46,1.5 -68.5,-3.2 -204.2,94.5 -524.8,179.9 -890.5,227.9 -242.6,31.9 -570.8,272.5 -853.6,469 40.1,153.4 74.2,327.7 98.7,513.9 17.4,132.5 28.4,260.4 33.7,380.4 0.9,20.9 1.6,41.5 2.2,61.9 102.2,140.7 160.6,254.7 171.7,334.9 146.6,101.3 290.1,206.2 425.5,312.6 94.5,74.3 186.3,144.3 274.9,210.9 323.5,243.3 601.7,440.3 795.1,626.5 239.4,-336.9 587.3,-500.1 789.4,-364.5 144.8,97.1 192.2,434.7 126.7,751.4 151.3,60.1 258.4,207.6 258.4,380.3 0,226.1 -183.3,409.5 -409.5,409.5 -53.4,0 -104.3,-10.6 -151.1,-29.2 41.3,147 102.8,289 182.7,424.4 236.5,401.5 634.1,745.9 1137.5,989.6 503.4,243.7 1111.9,386.5 1767.9,386.5 v 99.8 c -893.9,-0.1 -1703.5,-259 -2292.2,-680.9 -294.2,-210.9 -533.4,-462.9 -699.2,-744.3" - style="fill:#bfe142;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path16" /><path - d="m 14096.4,15241.1 c -14.7,4.9 -30.1,8.2 -46.6,8.2 -81.6,0 -147.8,-66.2 -147.8,-148 0,-4.7 0.9,-9.3 1.4,-14 7.1,-75 69.6,-133.8 146.4,-133.8 81.7,0 148,66.2 148,147.8 0,65.3 -42.6,120.1 -101.4,139.8" - style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path18" /><path - d="m 14139.5,14802.3 c -153.4,0 -277.7,222.5 -277.7,222.5 0,0 15.3,27.3 41.6,62.5 -0.5,4.7 -1.4,9.3 -1.4,14 0,81.8 66.2,148 147.8,148 16.5,0 31.9,-3.3 46.6,-8.2 14.1,3.6 28.4,6.2 43.1,6.2 153.3,0 277.6,-222.5 277.6,-222.5 0,0 -124.3,-222.5 -277.6,-222.5 z m 238.4,499.7 c -67.2,48.3 -149.3,77.1 -238.4,77.1 -226.1,0 -409.5,-183.4 -409.5,-409.5 0,-37.7 5.5,-73.9 15,-108.5 47.6,-173.4 206,-301 394.5,-301 56.5,0 110.3,11.5 159.4,32.2 147,62.1 250,207.7 250,377.3 0,104.3 -39.3,199.3 -103.6,271.7 -20.1,22.6 -42.7,43 -67.4,60.7" - style="fill:#d4e61d;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path20" /><path - d="m 14139.5,15247.3 c -14.7,0 -29,-2.6 -43.1,-6.2 58.8,-19.7 101.4,-74.5 101.4,-139.8 0,-81.6 -66.3,-147.8 -148,-147.8 -76.8,0 -139.3,58.8 -146.4,133.8 -26.3,-35.2 -41.6,-62.5 -41.6,-62.5 0,0 124.3,-222.5 277.7,-222.5 153.3,0 277.6,222.5 277.6,222.5 0,0 -124.3,222.5 -277.6,222.5" - style="fill:#293519;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path22" /><path - d="m 5843.09,10913.9 1.01,4.3 c 120.16,-58.3 516.88,-510.3 835.31,-813.7 159.85,99.8 327,200.2 501.61,300.9 -364.5,119.2 -1220.16,989.6 -1442,982.7 -18.82,13.2 -39.37,23.6 -61.83,29.8 -157.03,43.9 -337.35,-110.8 -402.78,-345.3 -27.89,-100 -231.91,-1141.6 -444.61,-2306.9 181.65,149.7 379.42,307.9 595.2,472.1 221.99,884.7 395.16,1594 418.09,1676.1" - style="fill:#96d42f;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path24" /><path - d="m 4332.03,5382.5 c 76.92,-21.4 425.39,1249.4 768.63,2579.1 -153.51,-57.3 -301.56,-110.7 -443.36,-160 C 4437.54,6545 4260.27,5402.5 4332.03,5382.5" - style="fill:#96d42f;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path26" /><path - d="m 8577.89,11337.9 2.89,-3.4 c 23.01,-24.8 112.07,-126.4 248.52,-282.4 214.45,49.5 423.43,89.7 628.86,130 -243.75,309.5 -410.74,517.5 -444.37,553.8 -165.47,178.5 -396.56,233.5 -516.09,122.7 -17.15,-15.9 -30.67,-34.5 -41.37,-54.8 -133.2,-63.4 -338.01,-599.7 -539.53,-1032.4 175.93,70.8 347.18,128.4 514.76,177.3 58.36,189 109.38,339.9 146.33,389.2" - style="fill:#96d42f;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path28" /><path - d="m 12455.6,7107.7 c 78.1,72.5 -1347,1953 -2389,3295.7 -140,-89.5 -284.53,-179.5 -433.4,-269.7 1121.5,-1276.9 2742.7,-3099.8 2822.4,-3026" - style="fill:#96d42f;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path30" /><path - d="m 14364.1,11431.3 c 253.8,-33.3 491,-43.5 686.6,-33.8 l -0.7,-4.4 c -31.7,-241.4 1000.4,-3750.9 1162.1,-3772.1 161.7,-21.2 -608.5,3453.9 -576.8,3695.3 31.7,241.4 -73.7,454.3 -235.3,475.5 -23.1,3.1 -46.1,1.6 -68.6,-3.1 -204.2,94.5 -524.7,179.9 -890.5,227.9 -242.6,31.9 -570.8,272.5 -853.6,469 40.1,153.3 74.3,327.7 98.7,513.9 27.3,207.8 39,404.5 37.1,576.4 -88.6,-66.6 -180.4,-136.6 -274.9,-210.9 -135.4,-106.4 -278.9,-211.3 -425.5,-312.6 -11.1,-80.2 -69.5,-194.2 -171.7,-334.9 -0.6,-20.4 -1.3,-41 -2.2,-61.9 90.5,-311.4 213.1,-585.2 307.7,-709 97.4,-159.7 600.2,-435.6 1207.6,-515.3" - style="fill:#96d42f;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path32" /></g></g></svg> diff --git a/web/public/world-trading-background.webp b/web/public/world-trading-background.webp deleted file mode 100644 index 502beb2903f52fadc98d35377b37f58bc9713f44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272522 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%0A!Kt*6vF!qBIG%;+SSgThfl<@aG~bR}KlX~hB1 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∨0J7AJ*R{VLU! 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 diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 7bea3ec2..57bc2dc5 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -15,9 +15,6 @@ module.exports = { } ), extend: { - backgroundImage: { - 'world-trading': "url('/world-trading-background.webp')", - }, colors: { 'greyscale-1': '#FBFBFF', 'greyscale-2': '#E7E7F4', From 5a10132e2b25f186cbb6c2f09557627445743dab Mon Sep 17 00:00:00 2001 From: FRC <pico2x@gmail.com> Date: Fri, 23 Sep 2022 15:11:50 -0400 Subject: [PATCH 31/60] Add a "Posts" tab to groups (#926) * Add a "Posts" sidebar item to groups * Fix James's nits * Show "Add Post" button only to users --- common/group.ts | 1 + functions/src/create-group.ts | 1 + functions/src/create-post.ts | 15 ++- functions/src/scripts/convert-tag-to-group.ts | 1 + web/components/create-post.tsx | 94 ++++++++++++++ web/components/groups/group-about-post.tsx | 18 ++- web/hooks/use-post.ts | 26 ++++ web/lib/firebase/api.ts | 6 +- web/lib/firebase/groups.ts | 1 + web/lib/firebase/posts.ts | 5 + web/pages/create-post.tsx | 93 ------------- web/pages/group/[...slugs]/index.tsx | 122 +++++++++++++++++- 12 files changed, 272 insertions(+), 111 deletions(-) create mode 100644 web/components/create-post.tsx delete mode 100644 web/pages/create-post.tsx diff --git a/common/group.ts b/common/group.ts index 871bc821..5220a1e8 100644 --- a/common/group.ts +++ b/common/group.ts @@ -10,6 +10,7 @@ export type Group = { totalContracts: number totalMembers: number aboutPostId?: string + postIds: string[] chatDisabled?: boolean mostRecentContractAddedTime?: number cachedLeaderboard?: { diff --git a/functions/src/create-group.ts b/functions/src/create-group.ts index 9d00bb0b..76dc1298 100644 --- a/functions/src/create-group.ts +++ b/functions/src/create-group.ts @@ -61,6 +61,7 @@ export const creategroup = newEndpoint({}, async (req, auth) => { anyoneCanJoin, totalContracts: 0, totalMembers: memberIds.length, + postIds: [], } await groupRef.create(group) diff --git a/functions/src/create-post.ts b/functions/src/create-post.ts index 40d39bba..113a34bd 100644 --- a/functions/src/create-post.ts +++ b/functions/src/create-post.ts @@ -34,11 +34,12 @@ const contentSchema: z.ZodType<JSONContent> = z.lazy(() => const postSchema = z.object({ title: z.string().min(1).max(MAX_POST_TITLE_LENGTH), content: contentSchema, + groupId: z.string().optional(), }) export const createpost = newEndpoint({}, async (req, auth) => { const firestore = admin.firestore() - const { title, content } = validate(postSchema, req.body) + const { title, content, groupId } = validate(postSchema, req.body) const creator = await getUser(auth.uid) if (!creator) @@ -60,6 +61,18 @@ export const createpost = newEndpoint({}, async (req, auth) => { } await postRef.create(post) + if (groupId) { + const groupRef = firestore.collection('groups').doc(groupId) + const group = await groupRef.get() + if (group.exists) { + const groupData = group.data() + if (groupData) { + const postIds = groupData.postIds ?? [] + postIds.push(postRef.id) + await groupRef.update({ postIds }) + } + } + } return { status: 'success', post } }) diff --git a/functions/src/scripts/convert-tag-to-group.ts b/functions/src/scripts/convert-tag-to-group.ts index 3240357e..b2e4c4d8 100644 --- a/functions/src/scripts/convert-tag-to-group.ts +++ b/functions/src/scripts/convert-tag-to-group.ts @@ -41,6 +41,7 @@ const createGroup = async ( anyoneCanJoin: true, totalContracts: contracts.length, totalMembers: 1, + postIds: [], } await groupRef.create(group) // create a GroupMemberDoc for the creator diff --git a/web/components/create-post.tsx b/web/components/create-post.tsx new file mode 100644 index 00000000..c176e61d --- /dev/null +++ b/web/components/create-post.tsx @@ -0,0 +1,94 @@ +import { useState } from 'react' +import { Spacer } from 'web/components/layout/spacer' +import { Title } from 'web/components/title' +import Textarea from 'react-expanding-textarea' + +import { TextEditor, useTextEditor } from 'web/components/editor' +import { createPost } from 'web/lib/firebase/api' +import clsx from 'clsx' +import Router from 'next/router' +import { MAX_POST_TITLE_LENGTH } from 'common/post' +import { postPath } from 'web/lib/firebase/posts' +import { Group } from 'common/group' + +export function CreatePost(props: { group?: Group }) { + const [title, setTitle] = useState('') + const [error, setError] = useState('') + const [isSubmitting, setIsSubmitting] = useState(false) + + const { group } = props + + const { editor, upload } = useTextEditor({ + disabled: isSubmitting, + }) + + const isValid = editor && title.length > 0 && editor.isEmpty === false + + async function savePost(title: string) { + if (!editor) return + const newPost = { + title: title, + content: editor.getJSON(), + groupId: group?.id, + } + + const result = await createPost(newPost).catch((e) => { + console.log(e) + setError('There was an error creating the post, please try again') + return e + }) + if (result.post) { + await Router.push(postPath(result.post.slug)) + } + } + + return ( + <div className="mx-auto w-full max-w-3xl"> + <div className="rounded-lg px-6 py-4 sm:py-0"> + <Title className="!mt-0" text="Create a post" /> + <form> + <div className="form-control w-full"> + <label className="label"> + <span className="mb-1"> + Title<span className={'text-red-700'}> *</span> + </span> + </label> + <Textarea + placeholder="e.g. Elon Mania Post" + className="input input-bordered resize-none" + autoFocus + maxLength={MAX_POST_TITLE_LENGTH} + value={title} + onChange={(e) => setTitle(e.target.value || '')} + /> + <Spacer h={6} /> + <label className="label"> + <span className="mb-1"> + Content<span className={'text-red-700'}> *</span> + </span> + </label> + <TextEditor editor={editor} upload={upload} /> + <Spacer h={6} /> + + <button + type="submit" + className={clsx( + 'btn btn-primary normal-case', + isSubmitting && 'loading disabled' + )} + disabled={isSubmitting || !isValid || upload.isLoading} + onClick={async () => { + setIsSubmitting(true) + await savePost(title) + setIsSubmitting(false) + }} + > + {isSubmitting ? 'Creating...' : 'Create a post'} + </button> + {error !== '' && <div className="text-red-700">{error}</div>} + </div> + </form> + </div> + </div> + ) +} diff --git a/web/components/groups/group-about-post.tsx b/web/components/groups/group-about-post.tsx index b76d8037..4d3046e9 100644 --- a/web/components/groups/group-about-post.tsx +++ b/web/components/groups/group-about-post.tsx @@ -16,29 +16,26 @@ import { usePost } from 'web/hooks/use-post' export function GroupAboutPost(props: { group: Group isEditable: boolean - post: Post + post: Post | null }) { const { group, isEditable } = props const post = usePost(group.aboutPostId) ?? props.post return ( <div className="rounded-md bg-white p-4 "> - {isEditable ? ( - <RichEditGroupAboutPost group={group} post={post} /> - ) : ( - <Content content={post.content} /> - )} + {isEditable && <RichEditGroupAboutPost group={group} post={post} />} + {!isEditable && post && <Content content={post.content} />} </div> ) } -function RichEditGroupAboutPost(props: { group: Group; post: Post }) { +function RichEditGroupAboutPost(props: { group: Group; post: Post | null }) { const { group, post } = props const [editing, setEditing] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false) const { editor, upload } = useTextEditor({ - defaultValue: post.content, + defaultValue: post?.content, disabled: isSubmitting, }) @@ -49,7 +46,7 @@ function RichEditGroupAboutPost(props: { group: Group; post: Post }) { content: editor.getJSON(), } - if (group.aboutPostId == null) { + if (post == null) { const result = await createPost(newPost).catch((e) => { console.error(e) return e @@ -65,6 +62,7 @@ function RichEditGroupAboutPost(props: { group: Group; post: Post }) { } async function deleteGroupAboutPost() { + if (post == null) return await deletePost(post) await deleteFieldFromGroup(group, 'aboutPostId') } @@ -91,7 +89,7 @@ function RichEditGroupAboutPost(props: { group: Group; post: Post }) { </> ) : ( <> - {group.aboutPostId == null ? ( + {post == null ? ( <div className="text-center text-gray-500"> <p className="text-sm"> No post has been added yet. diff --git a/web/hooks/use-post.ts b/web/hooks/use-post.ts index 9daf2d22..ff7bf6b9 100644 --- a/web/hooks/use-post.ts +++ b/web/hooks/use-post.ts @@ -11,3 +11,29 @@ export const usePost = (postId: string | undefined) => { return post } + +export const usePosts = (postIds: string[]) => { + const [posts, setPosts] = useState<Post[]>([]) + useEffect(() => { + if (postIds.length === 0) return + setPosts([]) + + const unsubscribes = postIds.map((postId) => + listenForPost(postId, (post) => { + if (post) { + setPosts((posts) => [...posts, post]) + } + }) + ) + + return () => { + unsubscribes.forEach((unsubscribe) => unsubscribe()) + } + }, [postIds]) + + return posts + .filter( + (post, index, self) => index === self.findIndex((t) => t.id === post.id) + ) + .sort((a, b) => b.createdTime - a.createdTime) +} diff --git a/web/lib/firebase/api.ts b/web/lib/firebase/api.ts index 6b1b43d8..8aa7a067 100644 --- a/web/lib/firebase/api.ts +++ b/web/lib/firebase/api.ts @@ -90,6 +90,10 @@ export function getCurrentUser(params: any) { return call(getFunctionUrl('getcurrentuser'), 'GET', params) } -export function createPost(params: { title: string; content: JSONContent }) { +export function createPost(params: { + title: string + content: JSONContent + groupId?: string +}) { return call(getFunctionUrl('createpost'), 'POST', params) } diff --git a/web/lib/firebase/groups.ts b/web/lib/firebase/groups.ts index 61424b8f..17e41c53 100644 --- a/web/lib/firebase/groups.ts +++ b/web/lib/firebase/groups.ts @@ -43,6 +43,7 @@ export function groupPath( | 'about' | typeof GROUP_CHAT_SLUG | 'leaderboards' + | 'posts' ) { return `/group/${groupSlug}${subpath ? `/${subpath}` : ''}` } diff --git a/web/lib/firebase/posts.ts b/web/lib/firebase/posts.ts index 162933af..36007048 100644 --- a/web/lib/firebase/posts.ts +++ b/web/lib/firebase/posts.ts @@ -39,3 +39,8 @@ export function listenForPost( ) { return listenForValue(doc(posts, postId), setPost) } + +export async function listPosts(postIds?: string[]) { + if (postIds === undefined) return [] + return Promise.all(postIds.map(getPost)) +} diff --git a/web/pages/create-post.tsx b/web/pages/create-post.tsx deleted file mode 100644 index 01147cc0..00000000 --- a/web/pages/create-post.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useState } from 'react' -import { Spacer } from 'web/components/layout/spacer' -import { Page } from 'web/components/page' -import { Title } from 'web/components/title' -import Textarea from 'react-expanding-textarea' - -import { TextEditor, useTextEditor } from 'web/components/editor' -import { createPost } from 'web/lib/firebase/api' -import clsx from 'clsx' -import Router from 'next/router' -import { MAX_POST_TITLE_LENGTH } from 'common/post' -import { postPath } from 'web/lib/firebase/posts' - -export default function CreatePost() { - const [title, setTitle] = useState('') - const [error, setError] = useState('') - const [isSubmitting, setIsSubmitting] = useState(false) - - const { editor, upload } = useTextEditor({ - disabled: isSubmitting, - }) - - const isValid = editor && title.length > 0 && editor.isEmpty === false - - async function savePost(title: string) { - if (!editor) return - const newPost = { - title: title, - content: editor.getJSON(), - } - - const result = await createPost(newPost).catch((e) => { - console.log(e) - setError('There was an error creating the post, please try again') - return e - }) - if (result.post) { - await Router.push(postPath(result.post.slug)) - } - } - - return ( - <Page> - <div className="mx-auto w-full max-w-3xl"> - <div className="rounded-lg px-6 py-4 sm:py-0"> - <Title className="!mt-0" text="Create a post" /> - <form> - <div className="form-control w-full"> - <label className="label"> - <span className="mb-1"> - Title<span className={'text-red-700'}> *</span> - </span> - </label> - <Textarea - placeholder="e.g. Elon Mania Post" - className="input input-bordered resize-none" - autoFocus - maxLength={MAX_POST_TITLE_LENGTH} - value={title} - onChange={(e) => setTitle(e.target.value || '')} - /> - <Spacer h={6} /> - <label className="label"> - <span className="mb-1"> - Content<span className={'text-red-700'}> *</span> - </span> - </label> - <TextEditor editor={editor} upload={upload} /> - <Spacer h={6} /> - - <button - type="submit" - className={clsx( - 'btn btn-primary normal-case', - isSubmitting && 'loading disabled' - )} - disabled={isSubmitting || !isValid || upload.isLoading} - onClick={async () => { - setIsSubmitting(true) - await savePost(title) - setIsSubmitting(false) - }} - > - {isSubmitting ? 'Creating...' : 'Create a post'} - </button> - {error !== '' && <div className="text-red-700">{error}</div>} - </div> - </form> - </div> - </div> - </Page> - ) -} diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index f06247cd..0dfe40a0 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -16,7 +16,7 @@ import { import { Row } from 'web/components/layout/row' import { firebaseLogin, getUser, User } from 'web/lib/firebase/users' import { Col } from 'web/components/layout/col' -import { useUser } from 'web/hooks/use-user' +import { useUser, useUserById } from 'web/hooks/use-user' import { useGroup, useGroupContractIds, @@ -42,10 +42,10 @@ import { GroupComment } from 'common/comment' import { REFERRAL_AMOUNT } from 'common/economy' import { UserLink } from 'web/components/user-link' import { GroupAboutPost } from 'web/components/groups/group-about-post' -import { getPost } from 'web/lib/firebase/posts' +import { getPost, listPosts, postPath } from 'web/lib/firebase/posts' import { Post } from 'common/post' import { Spacer } from 'web/components/layout/spacer' -import { usePost } from 'web/hooks/use-post' +import { usePost, usePosts } from 'web/hooks/use-post' import { useAdmin } from 'web/hooks/use-admin' import { track } from '@amplitude/analytics-browser' import { ArrowLeftIcon } from '@heroicons/react/solid' @@ -53,6 +53,10 @@ import { SelectMarketsModal } from 'web/components/contract-select-modal' import { BETTORS } from 'common/user' import { Page } from 'web/components/page' import { Tabs } from 'web/components/layout/tabs' +import { Avatar } from 'web/components/avatar' +import { Title } from 'web/components/title' +import { fromNow } from 'web/lib/util/time' +import { CreatePost } from 'web/components/create-post' export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { slugs: string[] } }) { @@ -70,7 +74,8 @@ export async function getStaticPropz(props: { params: { slugs: string[] } }) { ? 'all' : 'open' const aboutPost = - group && group.aboutPostId != null && (await getPost(group.aboutPostId)) + group && group.aboutPostId != null ? await getPost(group.aboutPostId) : null + const messages = group && (await listAllCommentsOnGroup(group.id)) const cachedTopTraderIds = @@ -83,6 +88,9 @@ export async function getStaticPropz(props: { params: { slugs: string[] } }) { const creator = await creatorPromise + const posts = ((group && (await listPosts(group.postIds))) ?? []).filter( + (p) => p != null + ) as Post[] return { props: { group, @@ -93,6 +101,7 @@ export async function getStaticPropz(props: { params: { slugs: string[] } }) { messages, aboutPost, suggestedFilter, + posts, }, revalidate: 60, // regenerate after a minute @@ -107,6 +116,7 @@ const groupSubpages = [ 'markets', 'leaderboards', 'about', + 'posts', ] as const export default function GroupPage(props: { @@ -116,8 +126,9 @@ export default function GroupPage(props: { topTraders: { user: User; score: number }[] topCreators: { user: User; score: number }[] messages: GroupComment[] - aboutPost: Post + aboutPost: Post | null suggestedFilter: 'open' | 'all' + posts: Post[] }) { props = usePropz(props, getStaticPropz) ?? { group: null, @@ -127,8 +138,9 @@ export default function GroupPage(props: { topCreators: [], messages: [], suggestedFilter: 'open', + posts: [], } - const { creator, topTraders, topCreators, suggestedFilter } = props + const { creator, topTraders, topCreators, suggestedFilter, posts } = props const router = useRouter() const { slugs } = router.query as { slugs: string[] } @@ -137,6 +149,12 @@ export default function GroupPage(props: { const group = useGroup(props.group?.id) ?? props.group const aboutPost = usePost(props.aboutPost?.id) ?? props.aboutPost + let groupPosts = usePosts(group?.postIds ?? []) ?? posts + + if (aboutPost != null) { + groupPosts = [aboutPost, ...groupPosts] + } + const user = useUser() const isAdmin = useAdmin() const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds @@ -172,6 +190,16 @@ export default function GroupPage(props: { </Col> ) + const postsPage = ( + <> + <Col> + <div className="mt-4 flex flex-col gap-8 px-4 md:flex-row"> + {posts && <GroupPosts posts={groupPosts} group={group} />} + </div> + </Col> + </> + ) + const aboutTab = ( <Col> {(group.aboutPostId != null || isCreator || isAdmin) && ( @@ -234,6 +262,10 @@ export default function GroupPage(props: { title: 'About', content: aboutTab, }, + { + title: 'Posts', + content: postsPage, + }, ] return ( @@ -413,6 +445,84 @@ function GroupLeaderboard(props: { ) } +function GroupPosts(props: { posts: Post[]; group: Group }) { + const { posts, group } = props + const [showCreatePost, setShowCreatePost] = useState(false) + const user = useUser() + + const createPost = <CreatePost group={group} /> + + const postList = ( + <div className=" align-start w-full items-start"> + <Row className="flex justify-between"> + <Col> + <Title text={'Posts'} className="!mt-0" /> + </Col> + <Col> + {user && ( + <Button + className="btn-md" + onClick={() => setShowCreatePost(!showCreatePost)} + > + Add a Post + </Button> + )} + </Col> + </Row> + + <div className="mt-2"> + {posts.map((post) => ( + <PostCard key={post.id} post={post} /> + ))} + {posts.length === 0 && ( + <div className="text-center text-gray-500">No posts yet</div> + )} + </div> + </div> + ) + + return showCreatePost ? createPost : postList +} + +function PostCard(props: { post: Post }) { + const { post } = props + const creatorId = post.creatorId + + const user = useUserById(creatorId) + + if (!user) return <> </> + + return ( + <div className="py-1"> + <Link href={postPath(post.slug)}> + <Row + className={ + 'relative gap-3 rounded-lg bg-white p-2 shadow-md hover:cursor-pointer hover:bg-gray-100' + } + > + <div className="flex-shrink-0"> + <Avatar className="h-12 w-12" username={user?.username} /> + </div> + <div className=""> + <div className="text-sm text-gray-500"> + <UserLink + className="text-neutral" + name={user?.name} + username={user?.username} + /> + <span className="mx-1">•</span> + <span className="text-gray-500">{fromNow(post.createdTime)}</span> + </div> + <div className="text-lg font-medium text-gray-900"> + {post.title} + </div> + </div> + </Row> + </Link> + </div> + ) +} + function AddContractButton(props: { group: Group; user: User }) { const { group, user } = props const [open, setOpen] = useState(false) From 57190e7876e5551044a63e99a9010004440fdb73 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 15:30:23 -0400 Subject: [PATCH 32/60] Daily trending sort option --- web/components/contract-search.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index 919cce86..331dcb80 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -48,6 +48,7 @@ import { Title } from './title' export const SORTS = [ { label: 'Newest', value: 'newest' }, { label: 'Trending', value: 'score' }, + { label: 'Daily trending', value: 'daily-score' }, { label: '24h volume', value: '24-hour-vol' }, { label: 'Last updated', value: 'last-updated' }, { label: 'Closing soon', value: 'close-date' }, @@ -88,6 +89,7 @@ export function ContractSearch(props: { hideGroupLink?: boolean hideQuickBet?: boolean noLinkAvatar?: boolean + showProbChange?: boolean } headerClassName?: string persistPrefix?: string @@ -128,6 +130,7 @@ export function ContractSearch(props: { numPages: 1, pages: [] as Contract[][], showTime: null as ShowTime | null, + showProbChange: false, }, !persistPrefix ? undefined @@ -181,8 +184,9 @@ export function ContractSearch(props: { const newPage = results.hits as any as Contract[] const showTime = sort === 'close-date' || sort === 'resolve-date' ? sort : null + const showProbChange = sort === 'daily-score' const pages = freshQuery ? [newPage] : [...state.pages, newPage] - setState({ numPages: results.nbPages, pages, showTime }) + setState({ numPages: results.nbPages, pages, showTime, showProbChange }) if (freshQuery && isWholePage) window.scrollTo(0, 0) } } @@ -200,6 +204,12 @@ export function ContractSearch(props: { }, 100) ).current + const updatedCardUIOptions = useMemo(() => { + if (cardUIOptions?.showProbChange === undefined && state.showProbChange) + return { ...cardUIOptions, showProbChange: true } + return cardUIOptions + }, [cardUIOptions, state.showProbChange]) + const contracts = state.pages .flat() .filter((c) => !additionalFilter?.excludeContractIds?.includes(c.id)) @@ -236,7 +246,7 @@ export function ContractSearch(props: { showTime={state.showTime ?? undefined} onContractClick={onContractClick} highlightOptions={highlightOptions} - cardUIOptions={cardUIOptions} + cardUIOptions={updatedCardUIOptions} /> )} </Col> From deb8397ee935c1ac8e9d685381b93f6e2bdaf953 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 15:33:48 -0400 Subject: [PATCH 33/60] Add Daily Trending section (daily-score for you.) Remove recently updated --- web/pages/home/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index f13fc200..de4e1c2f 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -106,9 +106,9 @@ export default function Home() { const HOME_SECTIONS = [ { label: 'Daily movers', id: 'daily-movers' }, + { label: 'Daily trending', id: 'daily-trending' }, { label: 'Trending', id: 'score' }, { label: 'New', id: 'newest' }, - { label: 'Recently updated', id: 'recently-updated-for-you' }, ] export const getHomeItems = (groups: Group[], sections: string[]) => { @@ -146,12 +146,12 @@ function renderSection( if (id === 'daily-movers') { return <DailyMoversSection key={id} userId={user?.id} /> } - if (id === 'recently-updated-for-you') + if (id === 'daily-trending') return ( <SearchSection key={id} label={label} - sort={'last-updated'} + sort={'daily-score'} pill="personal" user={user} /> From 0ab82a7bd49a89168e894938164529c278153367 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 15:40:48 -0400 Subject: [PATCH 34/60] Delete some unused code --- web/hooks/use-contracts.ts | 15 ------------ web/lib/firebase/contracts.ts | 46 ----------------------------------- 2 files changed, 61 deletions(-) diff --git a/web/hooks/use-contracts.ts b/web/hooks/use-contracts.ts index fb71ca60..053e2386 100644 --- a/web/hooks/use-contracts.ts +++ b/web/hooks/use-contracts.ts @@ -9,12 +9,10 @@ import { getUserBetContractsQuery, listAllContracts, trendingContractsQuery, - getContractsQuery, } from 'web/lib/firebase/contracts' import { QueryClient, useQuery, useQueryClient } from 'react-query' import { MINUTE_MS } from 'common/util/time' import { query, limit } from 'firebase/firestore' -import { Sort } from 'web/components/contract-search' import { dailyScoreIndex } from 'web/lib/service/algolia' import { CPMMBinaryContract } from 'common/contract' import { zipObject } from 'lodash' @@ -66,19 +64,6 @@ export const useTrendingContracts = (maxContracts: number) => { return result.data } -export const useContractsQuery = ( - sort: Sort, - maxContracts: number, - filters: { groupSlug?: string } = {}, - visibility?: 'public' -) => { - const result = useFirestoreQueryData( - ['contracts-query', sort, maxContracts, filters], - getContractsQuery(sort, maxContracts, filters, visibility) - ) - return result.data -} - export const useInactiveContracts = () => { const [contracts, setContracts] = useState<Contract[] | undefined>() diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts index 927f7187..d7f6cd88 100644 --- a/web/lib/firebase/contracts.ts +++ b/web/lib/firebase/contracts.ts @@ -24,7 +24,6 @@ import { Bet } from 'common/bet' import { Comment } from 'common/comment' import { ENV_CONFIG } from 'common/envs/constants' import { getBinaryProb } from 'common/contract-details' -import { Sort } from 'web/components/contract-search' export const contracts = coll<Contract>('contracts') @@ -321,51 +320,6 @@ export const getTopGroupContracts = async ( return await getValues<Contract>(creatorContractsQuery) } -const sortToField = { - newest: 'createdTime', - score: 'popularityScore', - 'most-traded': 'volume', - '24-hour-vol': 'volume24Hours', - 'prob-change-day': 'probChanges.day', - 'last-updated': 'lastUpdated', - liquidity: 'totalLiquidity', - 'close-date': 'closeTime', - 'resolve-date': 'resolutionTime', - 'prob-descending': 'prob', - 'prob-ascending': 'prob', -} as const - -const sortToDirection = { - newest: 'desc', - score: 'desc', - 'most-traded': 'desc', - '24-hour-vol': 'desc', - 'prob-change-day': 'desc', - 'last-updated': 'desc', - liquidity: 'desc', - 'close-date': 'asc', - 'resolve-date': 'desc', - 'prob-ascending': 'asc', - 'prob-descending': 'desc', -} as const - -export const getContractsQuery = ( - sort: Sort, - maxItems: number, - filters: { groupSlug?: string } = {}, - visibility?: 'public' -) => { - const { groupSlug } = filters - return query( - contracts, - where('isResolved', '==', false), - ...(visibility ? [where('visibility', '==', visibility)] : []), - ...(groupSlug ? [where('groupSlugs', 'array-contains', groupSlug)] : []), - orderBy(sortToField[sort], sortToDirection[sort]), - limit(maxItems) - ) -} - export const getRecommendedContracts = async ( contract: Contract, excludeBettorId: string, From 1a5dcdedccce44c46b38318023e41466c0bf1a8b Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 16:30:44 -0400 Subject: [PATCH 35/60] Delay prefetch by 1000ms. Don't prefetch portfolio history. --- common/util/time.ts | 3 +++ web/hooks/use-contracts.ts | 4 ++-- web/hooks/use-portfolio-history.ts | 4 ++-- web/hooks/use-prefetch.ts | 2 -- web/hooks/use-user-bets.ts | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/common/util/time.ts b/common/util/time.ts index 9afb8db4..81dc3600 100644 --- a/common/util/time.ts +++ b/common/util/time.ts @@ -1,3 +1,6 @@ export const MINUTE_MS = 60 * 1000 export const HOUR_MS = 60 * MINUTE_MS export const DAY_MS = 24 * HOUR_MS + +export const sleep = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)) diff --git a/web/hooks/use-contracts.ts b/web/hooks/use-contracts.ts index 053e2386..11aae65c 100644 --- a/web/hooks/use-contracts.ts +++ b/web/hooks/use-contracts.ts @@ -11,7 +11,7 @@ import { trendingContractsQuery, } from 'web/lib/firebase/contracts' import { QueryClient, useQuery, useQueryClient } from 'react-query' -import { MINUTE_MS } from 'common/util/time' +import { MINUTE_MS, sleep } from 'common/util/time' import { query, limit } from 'firebase/firestore' import { dailyScoreIndex } from 'web/lib/service/algolia' import { CPMMBinaryContract } from 'common/contract' @@ -86,7 +86,7 @@ export const usePrefetchUserBetContracts = (userId: string) => { const queryClient = useQueryClient() return queryClient.prefetchQuery( ['contracts', 'bets', userId], - () => getUserBetContracts(userId), + () => sleep(1000).then(() => getUserBetContracts(userId)), { staleTime: 5 * MINUTE_MS } ) } diff --git a/web/hooks/use-portfolio-history.ts b/web/hooks/use-portfolio-history.ts index 6cc1a84e..1ae5e7ee 100644 --- a/web/hooks/use-portfolio-history.ts +++ b/web/hooks/use-portfolio-history.ts @@ -1,6 +1,6 @@ import { useQueryClient } from 'react-query' import { useFirestoreQueryData } from '@react-query-firebase/firestore' -import { DAY_MS, HOUR_MS, MINUTE_MS } from 'common/util/time' +import { DAY_MS, HOUR_MS, MINUTE_MS, sleep } from 'common/util/time' import { getPortfolioHistory, getPortfolioHistoryQuery, @@ -17,7 +17,7 @@ export const usePrefetchPortfolioHistory = (userId: string, period: Period) => { const cutoff = getCutoff(period) return queryClient.prefetchQuery( ['portfolio-history', userId, cutoff], - () => getPortfolioHistory(userId, cutoff), + () => sleep(1000).then(() => getPortfolioHistory(userId, cutoff)), { staleTime: 15 * MINUTE_MS } ) } diff --git a/web/hooks/use-prefetch.ts b/web/hooks/use-prefetch.ts index 46d78b3c..0e83613b 100644 --- a/web/hooks/use-prefetch.ts +++ b/web/hooks/use-prefetch.ts @@ -1,5 +1,4 @@ import { usePrefetchUserBetContracts } from './use-contracts' -import { usePrefetchPortfolioHistory } from './use-portfolio-history' import { usePrefetchUserBets } from './use-user-bets' export function usePrefetch(userId: string | undefined) { @@ -7,6 +6,5 @@ export function usePrefetch(userId: string | undefined) { return Promise.all([ usePrefetchUserBets(maybeUserId), usePrefetchUserBetContracts(maybeUserId), - usePrefetchPortfolioHistory(maybeUserId, 'weekly'), ]) } diff --git a/web/hooks/use-user-bets.ts b/web/hooks/use-user-bets.ts index 3731fb07..c28b453d 100644 --- a/web/hooks/use-user-bets.ts +++ b/web/hooks/use-user-bets.ts @@ -7,13 +7,13 @@ import { getUserBetsQuery, listenForUserContractBets, } from 'web/lib/firebase/bets' -import { MINUTE_MS } from 'common/util/time' +import { MINUTE_MS, sleep } from 'common/util/time' export const usePrefetchUserBets = (userId: string) => { const queryClient = useQueryClient() return queryClient.prefetchQuery( ['bets', userId], - () => getUserBets(userId), + () => sleep(1000).then(() => getUserBets(userId)), { staleTime: MINUTE_MS } ) } From 77ddc456a26fd55aa87299d2db4ed001f4003476 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 16:39:17 -0400 Subject: [PATCH 36/60] Add new home section to top. --- web/pages/home/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index de4e1c2f..c1a5f477 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -127,6 +127,10 @@ export const getHomeItems = (groups: Group[], sections: string[]) => { const sectionItems = filterDefined(sections.map((id) => itemsById[id])) + // Add new home section items to the top. + sectionItems.unshift( + ...HOME_SECTIONS.filter((item) => !sectionItems.includes(item)) + ) // Add unmentioned items to the end. sectionItems.push(...items.filter((item) => !sectionItems.includes(item))) From 490734db00805cd86789a0443089693ff42b06e9 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 16:43:23 -0400 Subject: [PATCH 37/60] If no user, show loading on home --- web/pages/home/index.tsx | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index c1a5f477..fda80c50 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -45,6 +45,7 @@ import { usePrefetch } from 'web/hooks/use-prefetch' import { Title } from 'web/components/title' import { CPMMBinaryContract } from 'common/contract' import { useContractsByDailyScoreGroups } from 'web/hooks/use-contracts' +import { LoadingIndicator } from 'web/components/loading-indicator' export default function Home() { const user = useUser() @@ -82,13 +83,17 @@ export default function Home() { <DailyStats user={user} /> </Row> - <> - {sections.map((section) => - renderSection(section, user, groups, groupContracts) - )} + {!user ? ( + <LoadingIndicator /> + ) : ( + <> + {sections.map((section) => + renderSection(section, user, groups, groupContracts) + )} - <TrendingGroupsSection user={user} /> - </> + <TrendingGroupsSection user={user} /> + </> + )} </Col> <button type="button" @@ -142,13 +147,13 @@ export const getHomeItems = (groups: Group[], sections: string[]) => { function renderSection( section: { id: string; label: string }, - user: User | null | undefined, + user: User, groups: Group[] | undefined, groupContracts: Dictionary<CPMMBinaryContract[]> | undefined ) { const { id, label } = section if (id === 'daily-movers') { - return <DailyMoversSection key={id} userId={user?.id} /> + return <DailyMoversSection key={id} userId={user.id} /> } if (id === 'daily-trending') return ( @@ -214,7 +219,7 @@ function SectionHeader(props: { function SearchSection(props: { label: string - user: User | null | undefined | undefined + user: User sort: Sort pill?: string }) { @@ -240,7 +245,7 @@ function SearchSection(props: { function GroupSection(props: { group: Group - user: User | null | undefined | undefined + user: User contracts: CPMMBinaryContract[] }) { const { group, user, contracts } = props @@ -251,18 +256,16 @@ function GroupSection(props: { <Button color="gray-white" onClick={() => { - if (user) { - const homeSections = (user.homeSections ?? []).filter( - (id) => id !== group.id - ) - updateUser(user.id, { homeSections }) + const homeSections = (user.homeSections ?? []).filter( + (id) => id !== group.id + ) + updateUser(user.id, { homeSections }) - toast.promise(leaveGroup(group, user.id), { - loading: 'Unfollowing group...', - success: `Unfollowed ${group.name}`, - error: "Couldn't unfollow group, try again?", - }) - } + toast.promise(leaveGroup(group, user.id), { + loading: 'Unfollowing group...', + success: `Unfollowed ${group.name}`, + error: "Couldn't unfollow group, try again?", + }) }} > <XCircleIcon className={'h-5 w-5 flex-shrink-0'} aria-hidden="true" /> From 2891a47d8c0ae66317b8315efb27e2e34453d52e Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Fri, 23 Sep 2022 16:49:14 -0400 Subject: [PATCH 38/60] Support navigating to /about pages --- web/pages/group/[...slugs]/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index 0dfe40a0..d768a222 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -145,6 +145,9 @@ export default function GroupPage(props: { const router = useRouter() const { slugs } = router.query as { slugs: string[] } const page = slugs?.[1] as typeof groupSubpages[number] + const tabIndex = ['markets', 'leaderboard', 'about', 'posts'].indexOf( + page as any + ) const group = useGroup(props.group?.id) ?? props.group const aboutPost = usePost(props.aboutPost?.id) ?? props.aboutPost @@ -277,7 +280,8 @@ export default function GroupPage(props: { /> <TopGroupNavBar group={group} /> <div className={'relative p-2 pt-0 md:pt-2'}> - <Tabs className={'mb-2'} tabs={tabs} /> + {/* TODO: Switching tabs should also update the group path */} + <Tabs className={'mb-2'} tabs={tabs} defaultIndex={tabIndex} /> </div> </Page> ) From d04304bdac284a6145aeee8ae51fb0b77bfda952 Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Fri, 23 Sep 2022 17:04:32 -0400 Subject: [PATCH 39/60] Fix blank page on nav to groups --- web/pages/group/[...slugs]/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index d768a222..bed244eb 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -146,7 +146,7 @@ export default function GroupPage(props: { const { slugs } = router.query as { slugs: string[] } const page = slugs?.[1] as typeof groupSubpages[number] const tabIndex = ['markets', 'leaderboard', 'about', 'posts'].indexOf( - page as any + page ?? 'markets' ) const group = useGroup(props.group?.id) ?? props.group From 96dc060a0a9018900d78a57e04000541d617dad0 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Fri, 23 Sep 2022 14:55:06 -0700 Subject: [PATCH 40/60] Move react-masonry-css dependency to web package.json (#930) --- functions/package.json | 1 - web/package.json | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/package.json b/functions/package.json index ba59f090..65d1fc07 100644 --- a/functions/package.json +++ b/functions/package.json @@ -40,7 +40,6 @@ "mailgun-js": "0.22.0", "module-alias": "2.2.2", "node-fetch": "2", - "react-masonry-css": "1.0.16", "stripe": "8.194.0", "zod": "3.17.2" }, diff --git a/web/package.json b/web/package.json index 6ee29183..dc49306f 100644 --- a/web/package.json +++ b/web/package.json @@ -58,6 +58,7 @@ "react-instantsearch-hooks-web": "6.24.1", "react-query": "3.39.0", "react-twitter-embed": "4.0.4", + "react-masonry-css": "1.0.16", "string-similarity": "^4.0.4", "tippy.js": "6.3.7" }, From e2a8df6c3a9d82495ccb855ac624b52d1ea54183 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Fri, 23 Sep 2022 14:55:17 -0700 Subject: [PATCH 41/60] Nivo 0.74.0 -> 0.80.0 (#929) --- web/package.json | 6 +- yarn.lock | 222 ++++++++++++++++++++--------------------------- 2 files changed, 95 insertions(+), 133 deletions(-) diff --git a/web/package.json b/web/package.json index dc49306f..3ccbc96c 100644 --- a/web/package.json +++ b/web/package.json @@ -23,9 +23,9 @@ "@floating-ui/react-dom-interactions": "0.9.2", "@headlessui/react": "1.6.1", "@heroicons/react": "1.0.5", - "@nivo/core": "0.74.0", - "@nivo/line": "0.74.0", - "@nivo/tooltip": "0.74.0", + "@nivo/core": "0.80.0", + "@nivo/line": "0.80.0", + "@nivo/tooltip": "0.80.0", "@react-query-firebase/firestore": "0.4.2", "@tiptap/core": "2.0.0-beta.182", "@tiptap/extension-character-count": "2.0.0-beta.31", diff --git a/yarn.lock b/yarn.lock index 81cf80fa..b03bbcca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2553,102 +2553,99 @@ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz#27d71a95247a9eaee03d47adee7e3bd594514136" integrity sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA== -"@nivo/annotations@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/annotations/-/annotations-0.74.0.tgz#f4a3474fdf8812c3812c30e08d3277e209bec0f6" - integrity sha512-nxZLKDi9YEy2zZUsOtbYL/2oAgsxK5SVZ1P3Csll+cQ96uLU6sU7jmb67AwK0nDbYk7BD3sZf/O/A9r/MCK4Ow== +"@nivo/annotations@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/annotations/-/annotations-0.80.0.tgz#127e4801fff7370dcfb9acfe1e335781dd65cfd5" + integrity sha512-bC9z0CLjU07LULTMWsqpjovRtHxP7n8oJjqBQBLmHOGB4IfiLbrryBfu9+aEZH3VN2jXHhdpWUz+HxeZzOzsLg== dependencies: - "@nivo/colors" "0.74.0" - "@react-spring/web" "9.2.6" + "@nivo/colors" "0.80.0" + "@react-spring/web" "9.4.5" lodash "^4.17.21" -"@nivo/axes@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/axes/-/axes-0.74.0.tgz#cf7cf2277b7aca5449a040ddf3e0cf9891971199" - integrity sha512-27o1H+Br0AaeUTiRhy7OebqzYEWr1xznHOxd+Hn2Xz9kK1alGBiPgwXrkXV0Q9CtrsroQFnX2QR3JxRgOtC5fA== +"@nivo/axes@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/axes/-/axes-0.80.0.tgz#22788855ddc45bb6a619dcd03d62d4bd8c0fc35f" + integrity sha512-AsUyaSHGwQVSEK8QXpsn8X+poZxvakLMYW7crKY1xTGPNw+SU4SSBohPVumm2jMH3fTSLNxLhAjWo71GBJXfdA== dependencies: - "@nivo/scales" "0.74.0" - "@react-spring/web" "9.2.6" + "@nivo/scales" "0.80.0" + "@react-spring/web" "9.4.5" d3-format "^1.4.4" d3-time-format "^3.0.0" -"@nivo/colors@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/colors/-/colors-0.74.0.tgz#29d1e7c6f3bcab4e872a168651b3a90cfba03a4f" - integrity sha512-5ClckmBm3x2XdJqHMylr6erY+scEL/twoGVfyXak/L+AIhL+Gf9PQxyxyfl3Lbtc3SPeAQe0ZAO1+VrmTn7qlA== +"@nivo/colors@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/colors/-/colors-0.80.0.tgz#5b70b4979df246d9d0d69fb638bba9764dd88b52" + integrity sha512-T695Zr411FU4RPo7WDINOAn8f79DPP10SFJmDdEqELE+cbzYVTpXqLGZ7JMv88ko7EOf9qxLQgcBqY69rp9tHQ== dependencies: d3-color "^2.0.0" d3-scale "^3.2.3" d3-scale-chromatic "^2.0.0" lodash "^4.17.21" - react-motion "^0.5.2" -"@nivo/core@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/core/-/core-0.74.0.tgz#7634c78a36a8bd50a0c04c6b6f12b779a88ec2f4" - integrity sha512-LZ3kN1PiEW0KU4PTBgaHFO757amyKZkEL4mKdAzvyNQtpq5idB3OhC/sYrBxhJaLqYcX19MgNfhIel/0KygHAg== +"@nivo/core@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/core/-/core-0.80.0.tgz#d180cb2622158eb7bc5f984131ff07984f12297e" + integrity sha512-6caih0RavXdWWSfde+rC2pk17WrX9YQlqK26BrxIdXzv3Ydzlh5SkrC7dR2TEvMGBhunzVeLOfiC2DWT1S8CFg== dependencies: - "@nivo/recompose" "0.74.0" - "@react-spring/web" "9.2.6" + "@nivo/recompose" "0.80.0" + "@react-spring/web" "9.4.5" d3-color "^2.0.0" d3-format "^1.4.4" - d3-hierarchy "^1.1.8" d3-interpolate "^2.0.1" d3-scale "^3.2.3" d3-scale-chromatic "^2.0.0" d3-shape "^1.3.5" d3-time-format "^3.0.0" lodash "^4.17.21" - resize-observer-polyfill "^1.5.1" -"@nivo/legends@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/legends/-/legends-0.74.0.tgz#8e5e04b2a3f980c2073a394d94c4d89fa8bc8724" - integrity sha512-Bfk392ngre1C8UaGoymwqK0acjjzuk0cglUSNsr0z8BAUQIVGUPthtfcxbq/yUYGJL/cxWky2QKxi9r3C0FbmA== +"@nivo/legends@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/legends/-/legends-0.80.0.tgz#49edc54000075b4df055f86794a8c32810269d06" + integrity sha512-h0IUIPGygpbKIZZZWIxkkxOw4SO0rqPrqDrykjaoQz4CvL4HtLIUS3YRA4akKOVNZfS5agmImjzvIe0s3RvqlQ== -"@nivo/line@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/line/-/line-0.74.0.tgz#f1f430d64a81d2fe1a5fd49e5cfaa61242066927" - integrity sha512-uJssLII1UTfxrZkPrkki054LFUpSKeqS35ttwK6VLvyqs5r3SrSXn223vDRNaaxuop5oT/L3APUJQwQDqUcj3w== +"@nivo/line@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/line/-/line-0.80.0.tgz#ba541b0fcfd53b3a7ce865feb43c993b7cf4a7d4" + integrity sha512-6UAD/y74qq3DDRnVb+QUPvXYojxMtwXMipGSNvCGk8omv1QZNTaUrbV+eQacvn9yh//a0yZcWipnpq0tGJyJCA== dependencies: - "@nivo/annotations" "0.74.0" - "@nivo/axes" "0.74.0" - "@nivo/colors" "0.74.0" - "@nivo/legends" "0.74.0" - "@nivo/scales" "0.74.0" - "@nivo/tooltip" "0.74.0" - "@nivo/voronoi" "0.74.0" - "@react-spring/web" "9.2.6" + "@nivo/annotations" "0.80.0" + "@nivo/axes" "0.80.0" + "@nivo/colors" "0.80.0" + "@nivo/legends" "0.80.0" + "@nivo/scales" "0.80.0" + "@nivo/tooltip" "0.80.0" + "@nivo/voronoi" "0.80.0" + "@react-spring/web" "9.4.5" d3-shape "^1.3.5" -"@nivo/recompose@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/recompose/-/recompose-0.74.0.tgz#057e8e1154073d7f4cb01aa8d165c3914b8bdb54" - integrity sha512-qC9gzGvDIxocrJoozDjqqffOwDpuEZijeMV59KExnztCwIpQbIYVBsDdpvL+tXfWausigSlnGILGfereXJTLUQ== +"@nivo/recompose@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/recompose/-/recompose-0.80.0.tgz#572048aed793321a0bada1fd176b72df5a25282e" + integrity sha512-iL3g7j3nJGD9+mRDbwNwt/IXDXH6E29mhShY1I7SP91xrfusZV9pSFf4EzyYgruNJk/2iqMuaqn+e+TVFra44A== dependencies: react-lifecycles-compat "^3.0.4" -"@nivo/scales@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/scales/-/scales-0.74.0.tgz#ede12b899da9e3aee7921ebce40f227e670a430d" - integrity sha512-5mER71NgZGdgs8X2PgilBpAWMMGtTXrUuYOBQWDKDMgtc83MU+mphhiYfLv5e6ViZyUB5ebfEkfeIgStLqrcEA== +"@nivo/scales@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/scales/-/scales-0.80.0.tgz#39313fb97c8ae9633c2aa1e17adb57cb851e8a50" + integrity sha512-4y2pQdCg+f3n4TKXC2tYuq71veZM+xPRQbOTgGYJpuBvMc7pQsXF9T5z7ryeIG9hkpXkrlyjecU6XcAG7tLSNg== dependencies: d3-scale "^3.2.3" d3-time "^1.0.11" d3-time-format "^3.0.0" lodash "^4.17.21" -"@nivo/tooltip@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/tooltip/-/tooltip-0.74.0.tgz#60d94b0fecc2fc179ada3efa380e7e456982b4a5" - integrity sha512-h3PUgNFF5HUeQFfx19MWS1uGK8iUDymZNY+5PyaCWDFT+0/ldXBu8uw5WYRui2KwNdTym6F0E/aT7JKczDd85w== +"@nivo/tooltip@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/tooltip/-/tooltip-0.80.0.tgz#07ebef47eb708a0612bd6297d5ad156bbec19d34" + integrity sha512-qGmrreRwnCsYjn/LAuwBtxBn/tvG8y+rwgd4gkANLBAoXd3bzJyvmkSe+QJPhUG64bq57ibDK+lO2pC48a3/fw== dependencies: - "@react-spring/web" "9.2.6" + "@react-spring/web" "9.4.5" -"@nivo/voronoi@0.74.0": - version "0.74.0" - resolved "https://registry.yarnpkg.com/@nivo/voronoi/-/voronoi-0.74.0.tgz#4b427955ddabd86934a2bbb95a62ff53ee97c575" - integrity sha512-Q3267T1+Tlufn8LbmSYnO8x9gL+h/iwH2Uqc5CENHSZu2KPD0PB82vxpQnbDVhjadulI0rlrPA9fU3VY3q1zKg== +"@nivo/voronoi@0.80.0": + version "0.80.0" + resolved "https://registry.yarnpkg.com/@nivo/voronoi/-/voronoi-0.80.0.tgz#59cc7ed253dc1a5bbcf614a5ac37d2468d561599" + integrity sha512-zaJV3I3cRu1gHpsXCIEvp6GGlGY8P7D9CwAVCjYDGrz3W/+GKN0kA7qGyHTC97zVxJtfefxSPlP/GtOdxac+qw== dependencies: d3-delaunay "^5.3.0" d3-scale "^3.2.3" @@ -2747,50 +2744,51 @@ resolved "https://registry.yarnpkg.com/@react-query-firebase/firestore/-/firestore-0.4.2.tgz#6ae52768715aa0a5c0d903dd4fd953ed417ba635" integrity sha512-7eYp905+sfBRcBTdj7W7BAc3bI3V0D0kKca4/juOTnN4gyoNyaCNOCjLPY467dTq325hGs7BX0ol7Pw3JENdHA== -"@react-spring/animated@~9.2.6-beta.0": - version "9.2.6" - resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.2.6.tgz#58f30fb75d8bfb7ccbc156cfd6b974a8f3dfd54e" - integrity sha512-xjL6nmixYNDvnpTs1FFMsMfSC0tURwPCU3b2jWNriYGLfwZ7c/TcyaEZA7yiNnmdFnuR3f3Z27AqIgaFC083Cw== +"@react-spring/animated@~9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.4.5.tgz#dd9921c716a4f4a3ed29491e0c0c9f8ca0eb1a54" + integrity sha512-KWqrtvJSMx6Fj9nMJkhTwM9r6LIriExDRV6YHZV9HKQsaolUFppgkOXpC+rsL1JEtEvKv6EkLLmSqHTnuYjiIA== dependencies: - "@react-spring/shared" "~9.2.6-beta.0" - "@react-spring/types" "~9.2.6-beta.0" + "@react-spring/shared" "~9.4.5" + "@react-spring/types" "~9.4.5" -"@react-spring/core@~9.2.6-beta.0": - version "9.2.6" - resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.2.6.tgz#ae22338fe55d070caf03abb4293b5519ba620d93" - integrity sha512-uPHUxmu+w6mHJrfQTMtmGJ8iZEwiVxz9kH7dRyk69bkZJt9z+w0Oj3UF4J3VcECZsbm3HRhN2ogXSAaqGjwhQw== +"@react-spring/core@~9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.4.5.tgz#4616e1adc18dd10f5731f100ebdbe9518b89ba3c" + integrity sha512-83u3FzfQmGMJFwZLAJSwF24/ZJctwUkWtyPD7KYtNagrFeQKUH1I05ZuhmCmqW+2w1KDW1SFWQ43RawqfXKiiQ== dependencies: - "@react-spring/animated" "~9.2.6-beta.0" - "@react-spring/shared" "~9.2.6-beta.0" - "@react-spring/types" "~9.2.6-beta.0" + "@react-spring/animated" "~9.4.5" + "@react-spring/rafz" "~9.4.5" + "@react-spring/shared" "~9.4.5" + "@react-spring/types" "~9.4.5" -"@react-spring/rafz@~9.2.6-beta.0": - version "9.2.6" - resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.2.6.tgz#d97484003875bf5fb5e6ec22dee97cc208363e48" - integrity sha512-62SivLKEpo7EfHPkxO5J3g9Cr9LF6+1A1RVOMJhkcpEYtbdbmma/d63Xp8qpMPEpk7uuWxaTb6jjyxW33pW3sg== +"@react-spring/rafz@~9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.4.5.tgz#84f809f287f2a66bbfbc66195db340482f886bd7" + integrity sha512-swGsutMwvnoyTRxvqhfJBtGM8Ipx6ks0RkIpNX9F/U7XmyPvBMGd3GgX/mqxZUpdlsuI1zr/jiYw+GXZxAlLcQ== -"@react-spring/shared@~9.2.6-beta.0": - version "9.2.6" - resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.2.6.tgz#2c84e62cc0cfbbbbeb5546acd46c1f4b248bc562" - integrity sha512-Qrm9fopKG/RxZ3Rw+4euhrpnB3uXSyiON9skHbcBfmkkzagpkUR66MX1YLrhHw0UchcZuSDnXs0Lonzt1rpWag== +"@react-spring/shared@~9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.4.5.tgz#4c3ad817bca547984fb1539204d752a412a6d829" + integrity sha512-JhMh3nFKsqyag0KM5IIM8BQANGscTdd0mMv3BXsUiMZrcjQTskyfnv5qxEeGWbJGGar52qr5kHuBHtCjQOzniA== dependencies: - "@react-spring/rafz" "~9.2.6-beta.0" - "@react-spring/types" "~9.2.6-beta.0" + "@react-spring/rafz" "~9.4.5" + "@react-spring/types" "~9.4.5" -"@react-spring/types@~9.2.6-beta.0": - version "9.2.6" - resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.2.6.tgz#f60722fcf9f8492ae16d0bdc47f0ea3c2a16d2cf" - integrity sha512-l7mCw182DtDMnCI8CB9orgTAEoFZRtdQ6aS6YeEAqYcy3nQZPmPggIHH9DxyLw7n7vBPRSzu9gCvUMgXKpTflg== +"@react-spring/types@~9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.4.5.tgz#9c71e5ff866b5484a7ef3db822bf6c10e77bdd8c" + integrity sha512-mpRIamoHwql0ogxEUh9yr4TP0xU5CWyZxVQeccGkHHF8kPMErtDXJlxyo0lj+telRF35XNihtPTWoflqtyARmg== -"@react-spring/web@9.2.6": - version "9.2.6" - resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.2.6.tgz#c4fba69e1b1b43bd1d6a62346530cfb07f2be09b" - integrity sha512-0HkRsEYR/CO3Uw46FWDWaF2wg2rUXcWE2R9AoZXthEYLUn5w9uE1mf2Jel7BxBxWGQ73owkqSQv+klA1Hb+ViQ== +"@react-spring/web@9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.4.5.tgz#b92f05b87cdc0963a59ee149e677dcaff09f680e" + integrity sha512-NGAkOtKmOzDEctL7MzRlQGv24sRce++0xAY7KlcxmeVkR7LRSGkoXHaIfm9ObzxPMcPHQYQhf3+X9jepIFNHQA== dependencies: - "@react-spring/animated" "~9.2.6-beta.0" - "@react-spring/core" "~9.2.6-beta.0" - "@react-spring/shared" "~9.2.6-beta.0" - "@react-spring/types" "~9.2.6-beta.0" + "@react-spring/animated" "~9.4.5" + "@react-spring/core" "~9.4.5" + "@react-spring/shared" "~9.4.5" + "@react-spring/types" "~9.4.5" "@rushstack/eslint-patch@^1.1.3": version "1.1.3" @@ -5232,11 +5230,6 @@ d3-format@^1.4.4: resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== -d3-hierarchy@^1.1.8: - version "1.1.9" - resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" - integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ== - "d3-interpolate@1 - 2", "d3-interpolate@1.2.0 - 2", d3-interpolate@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163" @@ -9207,16 +9200,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -9661,7 +9644,7 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -9922,13 +9905,6 @@ raf-schd@^4.0.2: resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== -raf@^3.1.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" - integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== - dependencies: - performance-now "^2.1.0" - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -10128,15 +10104,6 @@ react-masonry-css@1.0.16: resolved "https://registry.yarnpkg.com/react-masonry-css/-/react-masonry-css-1.0.16.tgz#72b28b4ae3484e250534700860597553a10f1a2c" integrity sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ== -react-motion@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316" - integrity sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ== - dependencies: - performance-now "^0.2.0" - prop-types "^15.5.8" - raf "^3.1.0" - react-query@3.39.0: version "3.39.0" resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.0.tgz#0caca7b0da98e65008bbcd4df0d25618c2100050" @@ -10538,11 +10505,6 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -resize-observer-polyfill@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" - integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" From d990bc2f077c9085bb4185f7dc97bc1e2a602012 Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Fri, 23 Sep 2022 14:55:27 -0700 Subject: [PATCH 42/60] Remove images config from next.config.js (#931) --- web/next.config.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/web/next.config.js b/web/next.config.js index 21b375ba..cf727fd4 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -9,9 +9,6 @@ module.exports = { reactStrictMode: true, optimizeFonts: false, experimental: { - images: { - allowFutureImage: true, - }, scrollRestoration: true, externalDir: true, modularizeImports: { From 21c7130d3b303adb200d524d722e778ae479f2e3 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Fri, 23 Sep 2022 18:58:05 -0400 Subject: [PATCH 43/60] Filter out markets with undefined probChanges in dev --- web/hooks/use-prob-changes.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/hooks/use-prob-changes.tsx b/web/hooks/use-prob-changes.tsx index f2f3ce13..132cfd64 100644 --- a/web/hooks/use-prob-changes.tsx +++ b/web/hooks/use-prob-changes.tsx @@ -41,7 +41,7 @@ export const useProbChanges = ( const hits = uniqBy( [...positiveChanges.hits, ...negativeChanges.hits], (c) => c.id - ) + ).filter((c) => c.probChanges) return sortBy(hits, (c) => Math.abs(c.probChanges.day)).reverse() } From ae4d49d9603447757342e5a10fef7e9dbd714427 Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Sun, 25 Sep 2022 11:29:59 -0400 Subject: [PATCH 44/60] Generate markets for the Criticism and Red Teaming contest --- functions/package.json | 3 +- .../src/scripts/contest/create-markets.ts | 114 ++ .../contest/criticism-and-red-teaming.ts | 1219 +++++++++++++++++ functions/src/scripts/contest/scrape-ea.ts | 55 + yarn.lock | 174 ++- 5 files changed, 1550 insertions(+), 15 deletions(-) create mode 100644 functions/src/scripts/contest/create-markets.ts create mode 100644 functions/src/scripts/contest/criticism-and-red-teaming.ts create mode 100644 functions/src/scripts/contest/scrape-ea.ts diff --git a/functions/package.json b/functions/package.json index 65d1fc07..0397c5db 100644 --- a/functions/package.json +++ b/functions/package.json @@ -47,7 +47,8 @@ "@types/mailgun-js": "0.22.12", "@types/module-alias": "2.0.1", "@types/node-fetch": "2.6.2", - "firebase-functions-test": "0.3.3" + "firebase-functions-test": "0.3.3", + "puppeteer": "18.0.5" }, "private": true } diff --git a/functions/src/scripts/contest/create-markets.ts b/functions/src/scripts/contest/create-markets.ts new file mode 100644 index 00000000..f0d4962c --- /dev/null +++ b/functions/src/scripts/contest/create-markets.ts @@ -0,0 +1,114 @@ +// Run with `npx ts-node src/scripts/contest/create-markets.ts` + +import { data } from './criticism-and-red-teaming' + +// Dev API key for Cause Exploration Prizes (@CEP) +// const API_KEY = '188f014c-0ba2-4c35-9e6d-88252e281dbf' +// DEV API key for Criticism and Red Teaming (@CARTBot) +const API_KEY = '6ff1f78a-32fe-43b2-b31b-9e3c78c5f18c' + +type CEPSubmission = { + title: string + author?: string + link: string +} + +// Use the API to create a new market for this Cause Exploration Prize submission +async function postMarket(submission: CEPSubmission) { + const { title, author } = submission + const response = await fetch('https://dev.manifold.markets/api/v0/market', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Key ${API_KEY}`, + }, + body: JSON.stringify({ + outcomeType: 'BINARY', + question: `"${title}" by ${author ?? 'anonymous'}`, + description: makeDescription(submission), + closeTime: Date.parse('2022-09-30').valueOf(), + initialProb: 10, + // Super secret options: + // groupId: 'y2hcaGybXT1UfobK3XTx', // [DEV] CEP Tournament + groupId: 'h3MhjYbSSG6HbxY8ZTwE', // [DEV] CART + // groupId: 'cMcpBQ2p452jEcJD2SFw', // [PROD] Predict CEP + visibility: 'unlisted', + // TODO: Increase liquidity? + }), + }) + const data = await response.json() + console.log('Created market:', data.slug) +} + +async function postAll() { + for (const submission of data.slice(3, 6)) { + await postMarket(submission) + } +} +postAll() + +/* Example curl request: +$ curl https://manifold.markets/api/v0/market -X POST -H 'Content-Type: application/json' \ + -H 'Authorization: Key {...}' + --data-raw '{"outcomeType":"BINARY", \ + "question":"Is there life on Mars?", \ + "description":"I'm not going to type some long ass example description.", \ + "closeTime":1700000000000, \ + "initialProb":25}' +*/ + +function makeDescription(submission: CEPSubmission) { + const { title, author, link } = submission + return { + content: [ + { + content: [ + { text: `Will ${author ?? 'anonymous'}'s post "`, type: 'text' }, + { + marks: [ + { + attrs: { + target: '_blank', + href: link, + class: + 'no-underline !text-indigo-700 z-10 break-words hover:underline hover:decoration-indigo-400 hover:decoration-2', + }, + type: 'link', + }, + ], + type: 'text', + text: title, + }, + { text: '" win any prize in the ', type: 'text' }, + { + text: 'EA Criticism and Red Teaming Contest', + type: 'text', + marks: [ + { + attrs: { + target: '_blank', + class: + 'no-underline !text-indigo-700 z-10 break-words hover:underline hover:decoration-indigo-400 hover:decoration-2', + href: 'https://forum.effectivealtruism.org/posts/8hvmvrgcxJJ2pYR4X/announcing-a-contest-ea-criticism-and-red-teaming', + }, + type: 'link', + }, + ], + }, + { text: '?', type: 'text' }, + ], + type: 'paragraph', + }, + { type: 'paragraph' }, + { + type: 'iframe', + attrs: { + allowfullscreen: true, + src: link, + frameborder: 0, + }, + }, + ], + type: 'doc', + } +} diff --git a/functions/src/scripts/contest/criticism-and-red-teaming.ts b/functions/src/scripts/contest/criticism-and-red-teaming.ts new file mode 100644 index 00000000..0f19705a --- /dev/null +++ b/functions/src/scripts/contest/criticism-and-red-teaming.ts @@ -0,0 +1,1219 @@ +export const data = [ + // { + // "title": "Announcing a contest: EA Criticism and Red Teaming", + // "author": "Lizka", + // "link": "https://forum.effectivealtruism.org/posts/8hvmvrgcxJJ2pYR4X/announcing-a-contest-ea-criticism-and-red-teaming" + // }, + // { + // "title": "Pre-announcing a contest for critiques and red teaming", + // "author": "Lizka", + // "link": "https://forum.effectivealtruism.org/posts/Fx8pWSLKGwuqsfuRQ/pre-announcing-a-contest-for-critiques-and-red-teaming" + // }, + // { + // "title": "Resource for criticisms and red teaming", + // "author": "Lizka", + // "link": "https://forum.effectivealtruism.org/posts/uuQDgiJJaswEyyzan/resource-for-criticisms-and-red-teaming" + // }, + { + title: + 'Deworming and decay: replicating GiveWell’s cost-effectiveness analysis ', + author: 'JoelMcGuire', + link: 'https://forum.effectivealtruism.org/posts/MKiqGvijAXfcBHCYJ/deworming-and-decay-replicating-givewell-s-cost', + }, + { + title: 'Critiques of EA that I want to read', + author: 'abrahamrowe', + link: 'https://forum.effectivealtruism.org/posts/n3WwTz4dbktYwNQ2j/critiques-of-ea-that-i-want-to-read', + }, + { + title: 'My take on What We Owe the Future', + author: 'elifland', + link: 'https://forum.effectivealtruism.org/posts/9Y6Y6qoAigRC7A8eX/my-take-on-what-we-owe-the-future', + }, + { + title: + 'A Critical Review of Open Philanthropy’s Bet On Criminal Justice Reform', + author: 'NunoSempere', + link: 'https://forum.effectivealtruism.org/posts/h2N9qEbvQ6RHABcae/a-critical-review-of-open-philanthropy-s-bet-on-criminal', + }, + { + title: 'Leaning into EA Disillusionment', + author: 'Helen', + link: 'https://forum.effectivealtruism.org/posts/MjTB4MvtedbLjgyja/leaning-into-ea-disillusionment', + }, + { + title: 'Red Teaming CEA’s Community Building Work', + author: 'AnonymousEAForumAccount', + link: 'https://forum.effectivealtruism.org/posts/hbejbRBpd6quqnTAB/red-teaming-cea-s-community-building-work-2', + }, + { + title: + 'A philosophical review of Open Philanthropy’s Cause Prioritisation Framework', + author: 'MichaelPlant', + link: 'https://forum.effectivealtruism.org/posts/bdiDW83SFAsoA4EeB/a-philosophical-review-of-open-philanthropy-s-cause', + }, + { + title: 'The Future Might Not Be So Great', + author: 'Jacy', + link: 'https://forum.effectivealtruism.org/posts/WebLP36BYDbMAKoa5/the-future-might-not-be-so-great', + }, + { + title: 'Potatoes: A Critical Review', + author: 'Pablo Villalobos', + link: 'https://forum.effectivealtruism.org/posts/iZrrWGvx2s2uPtica/potatoes-a-critical-review', + }, + { + title: 'Effective Altruism as Coordination & Field Incubation', + author: 'DavidNash', + link: 'https://forum.effectivealtruism.org/posts/Zm6iaaJhoZsoZ2uMD/effective-altruism-as-coordination-and-field-incubation', + }, + { + title: 'Enlightenment Values in a Vulnerable World', + author: 'Maxwell Tabarrok', + link: 'https://forum.effectivealtruism.org/posts/A4fMkKhBxio83NtBL/enlightenment-values-in-a-vulnerable-world', + }, + { + title: "21 criticisms of EA I'm thinking about", + author: 'Peter Wildeford', + link: 'https://forum.effectivealtruism.org/posts/X47rn28Xy5TRfGgSj/21-criticisms-of-ea-i-m-thinking-about', + }, + { + title: 'Longtermism and Computational Complexity', + author: 'David Kinney', + link: 'https://forum.effectivealtruism.org/posts/RRyHcupuDafFNXt6p/longtermism-and-computational-complexity', + }, + { + title: 'The Community Manifesto', + author: 'dianaqianmorgan', + link: 'https://forum.effectivealtruism.org/posts/cY3wBXoJoeHXJ7XYt/the-community-manifesto', + }, + { + title: 'Existential risk pessimism and the time of perils', + author: 'David Thorstad', + link: 'https://forum.effectivealtruism.org/posts/N6hcw8CxK7D3FCD5v/existential-risk-pessimism-and-the-time-of-perils-4', + }, + { + title: "A critical review of GiveWell's 2022 cost-effectiveness model", + author: 'Froolow', + link: 'https://forum.effectivealtruism.org/posts/6dtwkwBrHBGtc3xes/a-critical-review-of-givewell-s-2022-cost-effectiveness', + }, + { + title: 'How EA is perceived is crucial to its future trajectory', + author: 'GidonKadosh', + link: 'https://forum.effectivealtruism.org/posts/82ig8odF9ooccfJfa/how-ea-is-perceived-is-crucial-to-its-future-trajectory', + }, + { + title: + 'Before There Was Effective Altruism, There Was Effective Philanthropy', + author: 'ColdButtonIssues', + link: 'https://forum.effectivealtruism.org/posts/CdrKtaAX69iJuJD2r/before-there-was-effective-altruism-there-was-effective', + }, + { + title: + 'A concern about the “evolutionary anchor” of Ajeya Cotra’s report on AI timelines.', + author: 'NunoSempere', + link: 'https://forum.effectivealtruism.org/posts/FHTyixYNnGaQfEexH/a-concern-about-the-evolutionary-anchor-of-ajeya-cotra-s', + }, + { + title: + 'EA is becoming increasingly inaccessible, at the worst possible time', + author: 'Ann Garth', + link: 'https://forum.effectivealtruism.org/posts/duPDKhtXTJNAJBaSf/ea-is-becoming-increasingly-inaccessible-at-the-worst', + }, + { + title: 'Red-teaming contest: demographics and power structures in EA', + author: 'TheOtherHannah', + link: 'https://forum.effectivealtruism.org/posts/oD3zus6LhbhBj6z2F/red-teaming-contest-demographics-and-power-structures-in-ea', + }, + { + title: 'The Nietzschean Challenge to Effective Altruism', + author: 'Richard Y Chappell', + link: 'https://forum.effectivealtruism.org/posts/bedstSbqaP8aDBfDr/the-nietzschean-challenge-to-effective-altruism', + }, + { + title: + 'The Case for Funding New Long-Term Randomized Controlled Trials of Deworming', + author: 'MHR', + link: 'https://forum.effectivealtruism.org/posts/CyxZmwQ7gADwjBHG6/the-case-for-funding-new-long-term-randomized-controlled', + }, + { + title: 'Population Ethics Without Axiology: A Framework', + author: 'Lukas_Gloor', + link: 'https://forum.effectivealtruism.org/posts/dQvDxDMyueLyydHw4/population-ethics-without-axiology-a-framework', + }, + { + title: 'Questioning the Value of Extinction Risk Reduction', + author: 'Red Team 8', + link: 'https://forum.effectivealtruism.org/posts/eeDsHDoM9De4iGGLw/questioning-the-value-of-extinction-risk-reduction-1', + }, + { + title: 'Red teaming introductory EA courses', + author: 'Philip Hall Andersen', + link: 'https://forum.effectivealtruism.org/posts/JDEDsCaQd2CYm7QEi/red-teaming-introductory-ea-courses', + }, + { + title: 'Systemic Cascading Risks: Relevance in Longtermism & Value Lock-In', + author: 'Richard Ren', + link: 'https://forum.effectivealtruism.org/posts/mWGodAi9Mv2a2EbNj/systemic-cascading-risks-relevance-in-longtermism-and-value', + }, + { + title: + 'community building solely as a tool for impact creates toxic communities', + author: 'ruthgrace', + link: 'https://forum.effectivealtruism.org/posts/EpMQBmQv7e4yaDYYN/community-building-solely-as-a-tool-for-impact-creates-toxic', + }, + { + title: + 'Are you really in a race? The Cautionary Tales of Szilárd and Ellsberg', + author: 'HaydnBelfield', + link: 'https://forum.effectivealtruism.org/posts/cXBznkfoPJAjacFoT/are-you-really-in-a-race-the-cautionary-tales-of-szilard-and', + }, + { + title: + "Quantifying Uncertainty in GiveWell's GiveDirectly Cost-Effectiveness Analysis", + author: 'Hazelfire', + link: 'https://forum.effectivealtruism.org/posts/ycLhq4Bmep8ssr4wR/quantifying-uncertainty-in-givewell-s-givedirectly-cost', + }, + { + title: 'Changing the world through slack & hobbies', + author: 'Steven Byrnes', + link: 'https://forum.effectivealtruism.org/posts/ZkhABk4rRMqsNmwvf/changing-the-world-through-slack-and-hobbies', + }, + { + title: + 'Some concerns about policy work funding and the Long Term Future Fund', + author: 'weeatquince', + link: 'https://forum.effectivealtruism.org/posts/Xfon9oxyMFv47kFnc/some-concerns-about-policy-work-funding-and-the-long-term', + }, + { + title: + 'Why Effective Altruists Should Put a Higher Priority on Funding Academic Research', + author: 'Stuart Buck', + link: 'https://forum.effectivealtruism.org/posts/uTQKFNXrMXuwGe4vw/why-effective-altruists-should-put-a-higher-priority-on', + }, + { + title: 'Remuneration In Effective Altruism', + author: 'Stefan_Schubert', + link: 'https://forum.effectivealtruism.org/posts/wWnRtjDiyjRRgaFDb/remuneration-in-effective-altruism', + }, + { + title: "You Don't Need To Justify Everything", + author: 'ThomasW', + link: 'https://forum.effectivealtruism.org/posts/HX9ZDGwwSxAab46N9/you-don-t-need-to-justify-everything', + }, + { + title: 'EAs underestimate uncertainty in cause prioritisation', + author: 'freedomandutility', + link: 'https://forum.effectivealtruism.org/posts/Ekd3oATEZkBbJ95uD/eas-underestimate-uncertainty-in-cause-prioritisation', + }, + { + title: '"Doing Good Best" isn\'t the EA ideal', + author: 'Davidmanheim', + link: 'https://forum.effectivealtruism.org/posts/f9NpDx65zY6Qk9ofe/doing-good-best-isn-t-the-ea-ideal', + }, + { + title: 'The discount rate is not zero', + author: 'Thomaaas', + link: 'https://forum.effectivealtruism.org/posts/zLZMsthcqfmv5J6Ev/the-discount-rate-is-not-zero', + }, + { + title: 'Questioning the Foundations of EA', + author: 'Wei_Dai', + link: 'https://forum.effectivealtruism.org/posts/zvNwSG2Xvy8x5Rtba/questioning-the-foundations-of-ea', + }, + { + title: + 'Notes on how prizes may fail and how to reduce the risk of them failing', + author: 'Peter Wildeford', + link: 'https://forum.effectivealtruism.org/posts/h2WcJf7pg5Qdfhsm3/notes-on-how-prizes-may-fail-and-how-to-reduce-the-risk-of', + }, + { + title: 'EA Culture and Causes: Less is More', + author: 'Allen Bell', + link: 'https://forum.effectivealtruism.org/posts/FWHDX32ecr9aF4xKw/ea-culture-and-causes-less-is-more', + }, + { + title: 'Things usually end slowly', + author: 'OllieBase', + link: 'https://forum.effectivealtruism.org/posts/qLwtCuh6nDCsrsrMK/things-usually-end-slowly', + }, + { + title: + 'Doing good is a privilege. This needs to change if we want to do good long-term. ', + author: 'SofiaBalderson', + link: 'https://forum.effectivealtruism.org/posts/gicYG5ymk4pPzrKAd/doing-good-is-a-privilege-this-needs-to-change-if-we-want-to', + }, + { + title: 'Animal Zoo', + author: 'bericlair', + link: 'https://forum.effectivealtruism.org/posts/YfmdnkmnoWBhmBaQL/animal-zoo', + }, + { + title: 'Summaries are underrated', + author: 'Nathan Young', + link: 'https://forum.effectivealtruism.org/posts/nDawZHxDR3j53zdbf/summaries-are-underrated', + }, + { + title: 'Longtermism, risk, and extinction', + author: 'Richard Pettigrew', + link: 'https://forum.effectivealtruism.org/posts/xAoZotkzcY5mvmXFY/longtermism-risk-and-extinction', + }, + { + title: + 'Prioritisation should consider potential for ongoing evaluation alongside expected value and evidence quality', + author: 'freedomandutility', + link: 'https://forum.effectivealtruism.org/posts/orfgdYRZXNKQtqzmh/prioritisation-should-consider-potential-for-ongoing', + }, + { + title: + '“Existential Risk” is badly named and leads to narrow focus on astronomical waste', + author: 'freedomandutility', + link: 'https://forum.effectivealtruism.org/posts/qFdifovCmckujxEsq/existential-risk-is-badly-named-and-leads-to-narrow-focus-on', + }, + { + title: + 'The great energy descent (short version) - An important thing EA might have missed', + author: 'Corentin Biteau', + link: 'https://forum.effectivealtruism.org/posts/wXzc75txE5hbHqYug/the-great-energy-descent-short-version-an-important-thing-ea', + }, + { + title: 'The Long Reflection as the Great Stagnation ', + author: 'Larks', + link: 'https://forum.effectivealtruism.org/posts/o5Q8dXfnHTozW9jkY/the-long-reflection-as-the-great-stagnation', + }, + { + title: 'Community posts: The Forum needs a way to work in public', + author: 'Nathan Young', + link: 'https://forum.effectivealtruism.org/posts/NxWssGagWoQWErRer/community-posts-the-forum-needs-a-way-to-work-in-public', + }, + { + title: 'Improving Karma: $8mn of possible value (my estimate)', + author: 'Nathan Young', + link: 'https://forum.effectivealtruism.org/posts/YajssmjwKndBTahQx/improving-karma-usd8mn-of-possible-value-my-estimate', + }, + { + title: 'Leveraging labor shortages as a pathway to career impact', + author: 'IanDavidMoss', + link: 'https://forum.effectivealtruism.org/posts/xdMn6FeQGjrXDPnQj/leveraging-labor-shortages-as-a-pathway-to-career-impact', + }, + { + title: 'How to dissolve moral cluelessness about donating mosquito nets', + author: 'ben.smith', + link: 'https://forum.effectivealtruism.org/posts/9XgLq4eQHMWybDsrv/how-to-dissolve-moral-cluelessness-about-donating-mosquito-1', + }, + { + title: '[TikTok] Comparability between suffering and happiness', + author: 'Ben_West', + link: 'https://forum.effectivealtruism.org/posts/ASmtarf3ADYb2Xmrt/tiktok-comparability-between-suffering-and-happiness', + }, + { + title: + 'Red teaming a model for estimating the value of longtermist interventions - A critique of Tarsney\'s "The Epistemic Challenge to Longtermism"', + author: 'Anjay F', + link: 'https://forum.effectivealtruism.org/posts/u9CvMCCmQRgjBD828/red-teaming-a-model-for-estimating-the-value-of-longtermist', + }, + { + title: + 'Criticism of EA Criticisms: Is the real disagreement about cause prio?', + author: 'Akash', + link: 'https://forum.effectivealtruism.org/posts/qgQaWub8iR2EERq7i/criticism-of-ea-criticisms-is-the-real-disagreement-about', + }, + { + title: 'Effective Altruism Should Seek Less Criticism', + author: 'The Chaostician', + link: 'https://forum.effectivealtruism.org/posts/oQA7Z6JKHAwvWz9wk/effective-altruism-should-seek-less-criticism', + }, + { + title: + 'The great energy descent - Part 1: Can renewables replace fossil fuels?', + author: 'Corentin Biteau', + link: 'https://forum.effectivealtruism.org/posts/qG8k5pzhaDk6FhcYv/the-great-energy-descent-part-1-can-renewables-replace', + }, + { + title: 'We’re searching for meaning, not happiness (et al.)', + author: 'Joshua Clingo', + link: 'https://forum.effectivealtruism.org/posts/gmTYoTmggojK5bywA/we-re-searching-for-meaning-not-happiness-et-al', + }, + { + title: + 'Earning to give should have focused more on “entrepreneurship to give”', + author: 'freedomandutility', + link: 'https://forum.effectivealtruism.org/posts/JXDi8tL6uoKPhg4uw/earning-to-give-should-have-focused-more-on-entrepreneurship', + }, + { + title: 'Longtermism neglects anti-ageing research', + author: 'freedomandutility', + link: 'https://forum.effectivealtruism.org/posts/pbPmhWhGxsGSzwpNE/longtermism-neglects-anti-ageing-research', + }, + { + title: + 'Popular EA Authors Should Give Libraries More Copies of Their EBooks', + author: 'RedTeamPseudonym', + link: 'https://forum.effectivealtruism.org/posts/AAL2zPtg7T6bjWijT/popular-ea-authors-should-give-libraries-more-copies-of', + }, + { + title: 'this one weird trick creates infinite utility', + author: 'Hmash', + link: 'https://forum.effectivealtruism.org/posts/BwuLaA97BAtLcbuuF/this-one-weird-trick-creates-infinite-utility', + }, + { + title: 'Think again: Should EA be a social movement?', + author: 'An A', + link: 'https://forum.effectivealtruism.org/posts/giznESHxt45SvuhZw/think-again-should-ea-be-a-social-movement', + }, + { + title: 'Rethinking longtermism and global development', + author: 'BrownHairedEevee', + link: 'https://forum.effectivealtruism.org/posts/GAEjbu2eHRXPHwTxF/rethinking-longtermism-and-global-development', + }, + { + title: 'Hiring: The Ignored Resource of Rejected EA Job Candidates', + author: 'RedTeamPseudonym', + link: 'https://forum.effectivealtruism.org/posts/ekLyLdiCCcD6BqbJR/hiring-the-ignored-resource-of-rejected-ea-job-candidates-1', + }, + { + title: 'Suggestions for 80,000K ', + author: 'RedTeamPseudonym', + link: 'https://forum.effectivealtruism.org/posts/MdvGwL4hTM2B96x4d/suggestions-for-80-000k', + }, + { + title: "We're funding task-adjusted survival (DALYs)", + author: 'brb243', + link: 'https://forum.effectivealtruism.org/posts/Gs8HS8QFBhtgAa8qo/we-re-funding-task-adjusted-survival-dalys', + }, + { + title: + 'A Need for Final Chapter Revision in Intro EA Fellowship Curricula & Other Ways to Fix Holes in The Funnel', + author: 'RedTeamPseudonym', + link: 'https://forum.effectivealtruism.org/posts/AaXDbHZhJYgxLCjYZ/a-need-for-final-chapter-revision-in-intro-ea-fellowship', + }, + { + title: 'Moral Injury, Mental Health, and Obsession in EA', + author: 'ECJ', + link: 'https://forum.effectivealtruism.org/posts/jiiyBcoZXXXT7eFHm/moral-injury-mental-health-and-obsession-in-ea', + }, + { + title: 'Are we already past the precipice?', + author: 'Dem0sthenes', + link: 'https://forum.effectivealtruism.org/posts/e6prpQSojPW3jC7YD/are-we-already-past-the-precipice', + }, + { + title: 'EA has a lying problem [Link Post]', + author: 'Nathan Young', + link: 'https://forum.effectivealtruism.org/posts/8dWms5YxYwZW9xneL/ea-has-a-lying-problem-link-post', + }, + { + title: + "Senior EA 'ops' roles: if you want to undo the bottleneck, hire differently", + author: 'AnonymousThrowAway', + link: 'https://forum.effectivealtruism.org/posts/X8YMxbWNsF5FNaCFz/senior-ea-ops-roles-if-you-want-to-undo-the-bottleneck-hire', + }, + { + title: "On Deference and Yudkowsky's AI Risk Estimates", + author: 'Ben Garfinkel', + link: 'https://forum.effectivealtruism.org/posts/NBgpPaz5vYe3tH4ga/on-deference-and-yudkowsky-s-ai-risk-estimates', + }, + { + title: 'EA is too reliant on personal connections', + author: 'sawyer', + link: 'https://forum.effectivealtruism.org/posts/dvcpKuajunxdaZ6se/ea-is-too-reliant-on-personal-connections', + }, + { + title: 'Michael Nielsen\'s "Notes on effective altruism"', + author: 'Pablo', + link: 'https://forum.effectivealtruism.org/posts/JBAPssaYMMRfNqYt7/michael-nielsen-s-notes-on-effective-altruism', + }, + { + title: 'Effective altruism in the garden of ends', + author: 'tyleralterman', + link: 'https://forum.effectivealtruism.org/posts/AjxqsDmhGiW9g8ju6/effective-altruism-in-the-garden-of-ends', + }, + { + title: 'Critique of MacAskill’s “Is It Good to Make Happy People?”', + author: 'Magnus Vinding', + link: 'https://forum.effectivealtruism.org/posts/vZ4kB8gpvkfHLfz8d/critique-of-macaskill-s-is-it-good-to-make-happy-people', + }, + { + title: 'Effective altruism is no longer the right name for the movement', + author: 'ParthThaya', + link: 'https://forum.effectivealtruism.org/posts/2FB8tK9da89qksZ9E/effective-altruism-is-no-longer-the-right-name-for-the-1', + }, + { + title: 'Prioritizing x-risks may require caring about future people', + author: 'elifland', + link: 'https://forum.effectivealtruism.org/posts/rvvwCcixmEep4RSjg/prioritizing-x-risks-may-require-caring-about-future-people', + }, + { + title: 'Ways money can make things worse', + author: 'Jan_Kulveit', + link: 'https://forum.effectivealtruism.org/posts/YKEPXLQhYjm3nP7Td/ways-money-can-make-things-worse', + }, + { + title: "EA Shouldn't Try to Exercise Direct Political Power", + author: 'iamasockpuppet', + link: 'https://forum.effectivealtruism.org/posts/BgNnctp6deoGdKtbr/ea-shouldn-t-try-to-exercise-direct-political-power', + }, + { + title: 'EA on nuclear war and expertise', + author: 'bean', + link: 'https://forum.effectivealtruism.org/posts/bCB88GKeXTaxozr6y/ea-on-nuclear-war-and-expertise', + }, + { + title: 'The most important climate change uncertainty', + author: 'cwa', + link: 'https://forum.effectivealtruism.org/posts/nBN6NENeudd2uJBCQ/the-most-important-climate-change-uncertainty', + }, + { + title: "Critique of OpenPhil's macroeconomic policy advocacy", + author: 'Hauke Hillebrandt', + link: 'https://forum.effectivealtruism.org/posts/cDdcNzyizzdZD4hbR/critique-of-openphil-s-macroeconomic-policy-advocacy', + }, + { + title: + 'Methods for improving uncertainty analysis in EA cost-effectiveness models', + author: 'Froolow', + link: 'https://forum.effectivealtruism.org/posts/CuuCGzuzwD6cdu9mo/methods-for-improving-uncertainty-analysis-in-ea-cost', + }, + { + title: + 'Did OpenPhil ever publish their in-depth review of their three-year OpenAI grant?', + author: 'Markus Amalthea Magnuson', + link: 'https://forum.effectivealtruism.org/posts/sZhhW2AECqT5JikdE/did-openphil-ever-publish-their-in-depth-review-of-their', + }, + { + title: 'Go Republican, Young EA!', + author: 'ColdButtonIssues', + link: 'https://forum.effectivealtruism.org/posts/myympkZ6SuT59vuEQ/go-republican-young-ea', + }, + { + title: + 'Are too many young, highly-engaged longtermist EAs doing movement-building?', + author: 'Anonymous_EA', + link: 'https://forum.effectivealtruism.org/posts/Lfy89vKqHatQdJgDZ/are-too-many-young-highly-engaged-longtermist-eas-doing', + }, + { + title: "EA's Culture and Thinking are Severely Limiting its Impact", + author: 'Peter Elam', + link: 'https://forum.effectivealtruism.org/posts/jhCGX8Gwq44TmyPJv/ea-s-culture-and-thinking-are-severely-limiting-its-impact', + }, + { + title: 'Criticism of EA Criticism Contest', + author: 'Zvi ', + link: 'https://forum.effectivealtruism.org/posts/qjMPATBLM5p4ABcEB/criticism-of-ea-criticism-contest', + }, + { + title: + 'The EA community might be neglecting the value of influencing people', + author: 'JulianHazell', + link: 'https://forum.effectivealtruism.org/posts/3szWd8HwWccJb9z5L/the-ea-community-might-be-neglecting-the-value-of', + }, + { + title: 'Slowing down AI progress is an underexplored alignment strategy', + author: 'Michael Huang', + link: 'https://forum.effectivealtruism.org/posts/6LNvQYyNQpDQmnnux/slowing-down-ai-progress-is-an-underexplored-alignment', + }, + { + title: 'Some core assumptions of effective altruism, according to me', + author: 'peterhartree', + link: 'https://forum.effectivealtruism.org/posts/av7MiEhi983SjoXTe/some-core-assumptions-of-effective-altruism-according-to-me', + }, + { + title: 'Transcript of Twitter Discussion on EA from June 2022', + author: 'Zvi ', + link: 'https://forum.effectivealtruism.org/posts/MpJcvzHfQyFLxLZNh/transcript-of-twitter-discussion-on-ea-from-june-2022', + }, + { + title: 'EA culture is special; we should proceed with intentionality', + author: 'James Lin', + link: 'https://forum.effectivealtruism.org/posts/KuKzqhxLzaREL7KKi/ea-culture-is-special-we-should-proceed-with-intentionality', + }, + { + title: 'Four Concerns Regarding Longtermism', + author: 'Pat Andriola', + link: 'https://forum.effectivealtruism.org/posts/ESzGcWfkMtJgF2CCA/four-concerns-regarding-longtermism', + }, + { + title: 'Chesterton Fences and EA’s X-risks', + author: 'jehan', + link: 'https://forum.effectivealtruism.org/posts/j4RnXAQgyMCSLzBkW/chesterton-fences-and-ea-s-x-risks', + }, + { + title: 'Introduction to Pragmatic AI Safety [Pragmatic AI Safety #1]', + author: 'ThomasW', + link: 'https://forum.effectivealtruism.org/posts/MskKEsj8nWREoMjQK/introduction-to-pragmatic-ai-safety-pragmatic-ai-safety-1', + }, + { + title: 'EA needs to understand its “failures” better', + author: 'mariushobbhahn', + link: 'https://forum.effectivealtruism.org/posts/Nwut6L6eAGmrFSaT4/ea-needs-to-understand-its-failures-better', + }, + { + title: 'An Evaluation of Animal Charity Evaluators ', + author: 'eaanonymous1234', + link: 'https://forum.effectivealtruism.org/posts/pfSiMpkmskRB4WxYW/an-evaluation-of-animal-charity-evaluators', + }, + { + title: 'What is the overhead of grantmaking?', + author: 'MathiasKB', + link: 'https://forum.effectivealtruism.org/posts/RXm2mxvq3ReXmsHm4/what-is-the-overhead-of-grantmaking', + }, + { + title: + 'A Critique of The Precipice: Chapter 6 - The Risk Landscape [Red Team Challenge]', + author: 'Sarah Weiler', + link: 'https://forum.effectivealtruism.org/posts/faW24r7ocbcPisgCH/a-critique-of-the-precipice-chapter-6-the-risk-landscape-red', + }, + { + title: + 'Wheeling and dealing: An internal bargaining approach to moral uncertainty', + author: 'MichaelPlant', + link: 'https://forum.effectivealtruism.org/posts/kxEAkcEvyiwmjirjN/wheeling-and-dealing-an-internal-bargaining-approach-to', + }, + { + title: 'Let’s not glorify people for how they look.', + author: 'Florence', + link: 'https://forum.effectivealtruism.org/posts/8ii5SD7HBL4EdYw5K/let-s-not-glorify-people-for-how-they-look-2', + }, + { + title: 'The first AGI will be a buggy mess', + author: 'titotal', + link: 'https://forum.effectivealtruism.org/posts/pXjpZep49M6GGxFQF/the-first-agi-will-be-a-buggy-mess', + }, + { + title: '[Cause Exploration Prizes] The importance of Intercausal Impacts', + author: 'Sebastian Joy 樂百善', + link: 'https://forum.effectivealtruism.org/posts/MayveXrHbvXMBRo78/cause-exploration-prizes-the-importance-of-intercausal', + }, + { + title: 'The Windfall Clause has a remedies problem', + author: 'John Bridge', + link: 'https://forum.effectivealtruism.org/posts/wBzfLyfJFfocmdrwL/the-windfall-clause-has-a-remedies-problem', + }, + { + title: 'Future Paths for Effective Altruism', + author: 'James Broughel', + link: 'https://forum.effectivealtruism.org/posts/yzAoHcTzf3AjeGYsP/future-paths-for-effective-altruism', + }, + { + title: 'The Effective Altruism culture', + author: 'PabloAMC', + link: 'https://forum.effectivealtruism.org/posts/NkF9rAjZpkDajqDDt/the-effective-altruism-culture', + }, + { + title: + 'The Role of Individual Consumption Decisions in Animal Welfare and Climate are Analogous', + author: 'Gabriel Weil', + link: 'https://forum.effectivealtruism.org/posts/HWpwfTF5M84jo4iyo/the-role-of-individual-consumption-decisions-in-animal', + }, + { + title: 'Criticism of the main framework in AI alignment', + author: 'Michele Campolo', + link: 'https://forum.effectivealtruism.org/posts/Cs8qhNakLuLXY4GvE/criticism-of-the-main-framework-in-ai-alignment', + }, + { + title: 'Crowdsourced Criticisms: What does EA think about EA?', + author: 'Hmash', + link: 'https://forum.effectivealtruism.org/posts/jK2Qends7GnyaRhm2/crowdsourced-criticisms-what-does-ea-think-about-ea', + }, + { + title: + 'EAs should recommend cost-effective interventions in more cause areas (not just the most pressing ones) \n\n', + author: 'Amber Dawn', + link: 'https://forum.effectivealtruism.org/posts/JiEyCNoGD3WwTgDkG/eas-should-recommend-cost-effective-interventions-in-more', + }, + { + title: + 'AGI Battle Royale: Why “slow takeover” scenarios devolve into a chaotic multi-AGI fight to the death', + author: 'titotal', + link: 'https://forum.effectivealtruism.org/posts/TxrzhfRr6EXiZHv4G/agi-battle-royale-why-slow-takeover-scenarios-devolve-into-a', + }, + { + title: 'Effective means to combat autocracies', + author: 'Junius Brutus', + link: 'https://forum.effectivealtruism.org/posts/kawE7rFmp3SkzLxpx/effective-means-to-combat-autocracies', + }, + { + title: 'Editing wild animals is underexplored in What We Owe the Future', + author: 'Michael Huang', + link: 'https://forum.effectivealtruism.org/posts/cWnQMagKFqJoaGA5M/editing-wild-animals-is-underexplored-in-what-we-owe-the', + }, + { + title: 'Reasons for my negative feelings towards the AI risk discussion', + author: 'fergusq', + link: 'https://forum.effectivealtruism.org/posts/hLbWWuDr3EbeQqrmg/reasons-for-my-negative-feelings-towards-the-ai-risk', + }, + { + title: + 'We need more discussion and clarity on how university groups create value', + author: 'Oscar Galvin', + link: 'https://forum.effectivealtruism.org/posts/HNHHNCDLEsDNjNwvm/we-need-more-discussion-and-clarity-on-how-university-groups', + }, + { + title: 'What 80000 Hours gets wrong about solar geoengineering', + author: 'Gideon Futerman', + link: 'https://forum.effectivealtruism.org/posts/6dbET4f9LbJZZTuDW/what-80000-hours-gets-wrong-about-solar-geoengineering', + }, + { + title: + 'Concerns/Thoughts over international aid, longtermism and philosophical notes on speaking with Larry Temkin.', + author: 'Ben Yeoh', + link: 'https://forum.effectivealtruism.org/posts/uhaKXdkAcuXJZHSci/concerns-thoughts-over-international-aid-longtermism-and', + }, + { + title: 'On longtermism, Bayesianism, and the doomsday argument', + author: 'iporphyry', + link: 'https://forum.effectivealtruism.org/posts/f2RzSd2ukFZyNB86L/on-longtermism-bayesianism-and-the-doomsday-argument', + }, + { + title: 'Friendship is Optimal: EAGs should be online', + author: 'Emrik', + link: 'https://forum.effectivealtruism.org/posts/35nRwEyzCKDfh3dCr/friendship-is-optimal-eags-should-be-online', + }, + { + title: 'A Critique of AI Takeover Scenarios', + author: 'Fods12', + link: 'https://forum.effectivealtruism.org/posts/j7X8nQ7YvvA7Pi4BX/a-critique-of-ai-takeover-scenarios', + }, + { + title: 'The dangers of high salaries within EA organisations', + author: 'James Ozden', + link: 'https://forum.effectivealtruism.org/posts/WXD3bRDBkcBhJ5Wcr/the-dangers-of-high-salaries-within-ea-organisations', + }, + { + title: 'Low-key Longtermism', + author: 'Jonathan Rystrom', + link: 'https://forum.effectivealtruism.org/posts/BaynHfmkjrfL8DXcK/low-key-longtermism', + }, + { + title: + 'The Credibility of Apocalyptic Claims: A Critique of Techno-Futurism within Existential Risk', + author: 'Ember', + link: 'https://forum.effectivealtruism.org/posts/a2XaDeadFe6eHfDwG/the-credibility-of-apocalyptic-claims-a-critique-of-techno', + }, + { + title: + 'The Role of "Economism" in the Belief-Formation Systems of Effective Altruism', + author: 'Thomas Aitken', + link: 'https://forum.effectivealtruism.org/posts/cR4pCrATD5SSN35Sm/the-role-of-economism-in-the-belief-formation-systems-of', + }, + { + title: + 'A slightly (I think?) different slant on why EA elitism bias/top-university focus/lack of diversity is a problem', + author: 'RedTeamPseudonym', + link: 'https://forum.effectivealtruism.org/posts/LCfQCvtFyAEnxCnMf/a-slightly-i-think-different-slant-on-why-ea-elitism-bias', + }, + { + title: 'Chaining the evil genie: why "outer" AI safety is probably easy', + author: 'titotal', + link: 'https://forum.effectivealtruism.org/posts/AoPR8BFrAFgGGN9iZ/chaining-the-evil-genie-why-outer-ai-safety-is-probably-easy', + }, + { + title: 'Should EA shift away (a bit) from elite universities?', + author: 'Joseph Lemien', + link: 'https://forum.effectivealtruism.org/posts/Rts8vKvbxkngPbFh7/should-ea-shift-away-a-bit-from-elite-universities', + }, + { + title: 'Aesthetics as Epistemic Humility', + author: 'Étienne Fortier-Dubois', + link: 'https://forum.effectivealtruism.org/posts/bo6Jsvmq9oiykbDrM/aesthetics-as-epistemic-humility', + }, + { + title: + "What if states don't listen? A fundamental gap in x-risk reduction strategies ", + author: 'HTC', + link: 'https://forum.effectivealtruism.org/posts/sFxtu6ZKAScDSqLrK/what-if-states-don-t-listen-a-fundamental-gap-in-x-risk', + }, + { + title: 'Eliminate or Adjust Strong Upvotes to Improve the Forum', + author: 'Afternoon Coffee', + link: 'https://forum.effectivealtruism.org/posts/2XGFdBkxa5Hm5LWZq/eliminate-or-adjust-strong-upvotes-to-improve-the-forum', + }, + { + title: 'On the Philosophical Foundations of EA', + author: 'mm6', + link: 'https://forum.effectivealtruism.org/posts/gLWmeKTe68ZHnomwy/on-the-philosophical-foundations-of-ea', + }, + { + title: + "Why I Hope (Certain) Hedonic Utilitarians Don't Control the Long-term Future", + author: 'Jared_Riggs', + link: 'https://forum.effectivealtruism.org/posts/PJKecg5ugYnyWhezC/why-i-hope-certain-hedonic-utilitarians-don-t-control-the', + }, + { + title: 'Be More Succinct', + author: 'RedTeamPseudonym', + link: 'https://forum.effectivealtruism.org/posts/eNa8GpEi5HX94CZ2n/be-more-succinct', + }, + { + title: 'Against Anthropic Shadow', + author: 'tobycrisford', + link: 'https://forum.effectivealtruism.org/posts/A47EWTS6oBKLqxBpw/against-anthropic-shadow', + }, + { + title: + 'Ideological tensions between Effective Altruism and The UK Civil Service', + author: 'KZ X', + link: 'https://forum.effectivealtruism.org/posts/J7cAFqq9g9LzSe5E3/ideological-tensions-between-effective-altruism-and-the-uk', + }, + { + title: 'We’re really bad at guessing the future', + author: 'Benj Azose', + link: 'https://forum.effectivealtruism.org/posts/DkmNPpqTJKmudBHnp/we-re-really-bad-at-guessing-the-future', + }, + { + title: + 'Effective Altruism, the Principle of Explosion and Epistemic Fragility', + author: 'Eigengender', + link: 'https://forum.effectivealtruism.org/posts/zG4pnJBCMi5t49Eya/effective-altruism-the-principle-of-explosion-and-epistemic', + }, + { + title: + 'Should EA influence governments to enact more effective interventions?', + author: 'Markus Amalthea Magnuson', + link: 'https://forum.effectivealtruism.org/posts/pGPcfjxazPGFJyYHW/should-ea-influence-governments-to-enact-more-effective', + }, + { + title: 'Should large EA nonprofits consider splitting?', + author: 'Arepo', + link: 'https://forum.effectivealtruism.org/posts/J3pZ7fY6yvypvJrJE/should-large-ea-nonprofits-consider-splitting', + }, + { + title: + "Evaluating large-scale movement building: A better way to critique Open Philanthropy's criminal justice reform", + author: 'ruthgrace', + link: 'https://forum.effectivealtruism.org/posts/7ajePuRKiCo7fA92B/evaluating-large-scale-movement-building-a-better-way-to', + }, + { + title: 'Evaluation of Longtermist Institutional Reform', + author: 'Dwarkesh Patel', + link: 'https://forum.effectivealtruism.org/posts/v4Z6phNcDsdXtzj2K/evaluation-of-longtermist-institutional-reform', + }, + { + title: 'A Quick List of Some Problems in AI Alignment As A Field', + author: 'NicholasKross', + link: 'https://forum.effectivealtruism.org/posts/JFmhYuso5s9PgrQET/a-quick-list-of-some-problems-in-ai-alignment-as-a-field', + }, + { + title: 'Fixing bad incentives in EA', + author: 'IncentivesAccount', + link: 'https://forum.effectivealtruism.org/posts/3PrTiXhhNBdGtR9qf/fixing-bad-incentives-in-ea', + }, + { + title: 'The danger of good stories', + author: 'DuncanS', + link: 'https://forum.effectivealtruism.org/posts/eZK95zxwpzNySRebC/the-danger-of-good-stories', + }, + { + title: 'A dilemma for Maximize Expected Choiceworthiness (MEC)', + author: 'Calvin_Baker', + link: 'https://forum.effectivealtruism.org/posts/Gk7NhzFy2hHFdFTYr/a-dilemma-for-maximize-expected-choiceworthiness-mec', + }, + { + title: 'Should you still use the ITN framework? [Red Teaming Contest]', + author: 'frib', + link: 'https://forum.effectivealtruism.org/posts/hjH94Ji4CrpKadoCi/should-you-still-use-the-itn-framework-red-teaming-contest', + }, + { + title: 'Proposed tweak to the longtermism pitch', + author: 'TheOtherHannah', + link: 'https://forum.effectivealtruism.org/posts/nAvpSXELT2FZMD9aA/proposed-tweak-to-the-longtermism-pitch', + }, + { + title: 'EA vs. FIRE – reconciling these two movements', + author: 'Stewed_Walrus', + link: 'https://forum.effectivealtruism.org/posts/j2ccaxmHcjiwGDs9T/ea-vs-fire-reconciling-these-two-movements', + }, + { + title: 'Should young EAs really focus on career capital?', + author: 'Michael B.', + link: 'https://forum.effectivealtruism.org/posts/RYBFyDWAYZL4YCkW2/should-young-eas-really-focus-on-career-capital', + }, + { + title: 'Prediction Markets are Somewhat Overrated Within EA', + author: 'Francis', + link: 'https://forum.effectivealtruism.org/posts/4LsrNczpF6mfrHP4M/prediction-markets-are-somewhat-overrated-within-ea', + }, + { + title: 'Capitalism, power and epistemology: a critique of EA', + author: 'Matthew_Doran', + link: 'https://forum.effectivealtruism.org/posts/xWFhD6uQuZehrDKeY/capitalism-power-and-epistemology-a-critique-of-ea', + }, + { + title: 'EA Worries and Criticism ', + author: 'Connor Tabarrok', + link: 'https://forum.effectivealtruism.org/posts/A5tRZC2mduJfpMhud/ea-worries-and-criticism', + }, + { + title: 'EA criticism contest: Why I am not an effective altruist', + author: 'ErikHoel', + link: 'https://forum.effectivealtruism.org/posts/PZ6pEaNkzAg62ze69/ea-criticism-contest-why-i-am-not-an-effective-altruist', + }, + { + title: 'Nuclear Fine-Tuning: How Many Worlds Have Been Destroyed?', + author: 'Ember', + link: 'https://forum.effectivealtruism.org/posts/Gg2YsjGe3oahw2kxE/nuclear-fine-tuning-how-many-worlds-have-been-destroyed', + }, + { + title: 'An epistemic critique of longtermism', + author: 'Nathan_Barnard', + link: 'https://forum.effectivealtruism.org/posts/2455tgtiBsm5KXBfv/an-epistemic-critique-of-longtermism', + }, + { + title: 'Red Team: Write More.', + author: 'Weaver', + link: 'https://forum.effectivealtruism.org/posts/5A5cMh223b9s4uHwE/red-team-write-more', + }, + { + title: 'End-To-End Encryption For EA', + author: 'Talking Tree', + link: 'https://forum.effectivealtruism.org/posts/tekdQKdfFe3YJTwML/end-to-end-encryption-for-ea', + }, + { + title: 'Effective Altruism is Unkind', + author: 'Oliver Scott Curry', + link: 'https://forum.effectivealtruism.org/posts/cC6tGHctzrMmEAH8j/effective-altruism-is-unkind', + }, + { + title: 'Towards a more ecumenical EA movement ', + author: 'Locke', + link: 'https://forum.effectivealtruism.org/posts/NR2Y2B8Y4Wxn8pAS8/towards-a-more-ecumenical-ea-movement', + }, + { + title: + 'Effective altruism is similar to the AI alignment problem and suffers from the same difficulties [Criticism and Red Teaming Contest entry]', + author: 'turchin', + link: 'https://forum.effectivealtruism.org/posts/g8fn7oyvki4psJeYR/effective-altruism-is-similar-to-the-ai-alignment-problem', + }, + { + title: + 'The great energy descent - Part 2: Limits to growth and why we probably won’t reach the stars', + author: 'Corentin Biteau', + link: 'https://forum.effectivealtruism.org/posts/8sW4h368DsoooHBNP/the-great-energy-descent-part-2-limits-to-growth-and-why-we', + }, + { + title: 'What a Large and Welcoming EA Could Accomplish', + author: 'Peter Elam', + link: 'https://forum.effectivealtruism.org/posts/K24widt85ZbGqzZKN/what-a-large-and-welcoming-ea-could-accomplish', + }, + { + title: 'Should we call ourselves effective altruists?', + author: 'Sam_Coggins', + link: 'https://forum.effectivealtruism.org/posts/YyDRSARnXz8r5dgca/should-we-call-ourselves-effective-altruists', + }, + { + title: 'Compounding assumptions and what it mean to be altruistic', + author: 'Badger', + link: 'https://forum.effectivealtruism.org/posts/4RGuqDxui2xWkXnda/compounding-assumptions-and-what-it-mean-to-be-altruistic', + }, + { + title: + 'The great energy descent - Post 3: What we can do, what we can’t do', + author: 'Corentin Biteau', + link: 'https://forum.effectivealtruism.org/posts/9zTLPy3zqJ7YfS7kn/the-great-energy-descent-post-3-what-we-can-do-what-we-can-t', + }, + { + title: 'Enantiodromia', + author: 'ChristianKleineidam', + link: 'https://forum.effectivealtruism.org/posts/b4ASDM434qh3rxLki/enantiodromia', + }, + { + title: 'Deontology, the Paralysis Argument and altruistic longtermism', + author: "William D'Alessandro", + link: 'https://forum.effectivealtruism.org/posts/DKe5eQhJoLNMWgaQv/deontology-the-paralysis-argument-and-altruistic-longtermism', + }, + { + title: 'Path dependence and its impact on long-term outcomes', + author: 'Archanaa', + link: 'https://forum.effectivealtruism.org/posts/jadS8deYknecGSebp/path-dependence-and-its-impact-on-long-term-outcomes', + }, + { + title: 'Histories of Value Lock-in and Ideology Critique', + author: 'clem', + link: 'https://forum.effectivealtruism.org/posts/poWd3CcGeQPas3Zbo/histories-of-value-lock-in-and-ideology-critique', + }, + { + title: 'A Case Against Strong Longtermism', + author: 'A. Wolff', + link: 'https://forum.effectivealtruism.org/posts/LADQ6dTGsQ2BBMrBv/a-case-against-strong-longtermism-1', + }, + { + title: 'The totalitarian implications of Effective Altruism', + author: 'Ed_Talks', + link: 'https://forum.effectivealtruism.org/posts/guyuidDdxNNxFegbJ/the-totalitarian-implications-of-effective-altruism-1', + }, + { + title: 'Forecasting Through Fiction', + author: 'Yitz', + link: 'https://forum.effectivealtruism.org/posts/DhJhtxMX6SdYAsWiY/forecasting-through-fiction', + }, + { + title: 'EA Undervalues Unseen Data', + author: 'tcelferact', + link: 'https://forum.effectivealtruism.org/posts/MpYPCq9dW8wovYpRY/ea-undervalues-unseen-data', + }, + { + title: 'The Happiness Maximizer:\nWhy EA is an x-risk', + author: 'Obasi Shaw', + link: 'https://forum.effectivealtruism.org/posts/ByHc6jdXF9skwevYf/the-happiness-maximizer-why-ea-is-an-x-risk', + }, + { + title: 'EA is a fight against Knightian uncertainty', + author: 'Rohit (Strange Loop)', + link: 'https://forum.effectivealtruism.org/posts/vic7EdWCGKd4fYtYd/ea-is-a-fight-against-knightian-uncertainty', + }, + { + title: + 'The Malthusian Gradient: Why some third-world interventions may be doing more harm than good', + author: 'JoePater', + link: 'https://forum.effectivealtruism.org/posts/juFzy7CWhu6ApQMAA/the-malthusian-gradient-why-some-third-world-interventions', + }, + { + title: 'The Hidden Impossibilities Of Being An Effective Altruist.', + author: 'Refined Insights ', + link: 'https://forum.effectivealtruism.org/posts/fsxEDLM2oPzSREM4G/the-hidden-impossibilities-of-being-an-effective-altruist', + }, + { + title: 'A critique of strong longtermism', + author: 'Pablo Rosado', + link: 'https://forum.effectivealtruism.org/posts/ryJys2fAz7J4vAwFC/a-critique-of-strong-longtermism', + }, + { + title: 'Making EA More Effective', + author: 'Peter Kelly', + link: 'https://forum.effectivealtruism.org/posts/Ag6bsmqxwqWTSjcHX/making-ea-more-effective', + }, + { + title: "A part of the system's apology", + author: 'Niv Cohen', + link: 'https://forum.effectivealtruism.org/posts/vNTD4mBAzfyZFJkfW/a-part-of-the-system-s-apology', + }, + { + title: 'The Wages of North-Atlantic Bias', + author: 'Sach Wry', + link: 'https://forum.effectivealtruism.org/posts/FA4tC72qAB5k37uFC/the-wages-of-north-atlantic-bias', + }, + { + title: 'Keeping it Real', + author: 'calumdavey', + link: 'https://forum.effectivealtruism.org/posts/ewEiyspZeqjZC7Yh7/keeping-it-real', + }, + { + title: 'Hobbit Manifesto', + author: 'Clay Cube', + link: 'https://forum.effectivealtruism.org/posts/3caZ7LhMsvsS7kRrz/hobbit-manifesto', + }, + { + title: + "How avoiding drastic career changes could support EA's epistemic health and long-term efficacy.", + author: 'nat goldthwaite', + link: 'https://forum.effectivealtruism.org/posts/3txJdk6ZcNmcRBjWP/how-avoiding-drastic-career-changes-could-support-ea-s', + }, + { + title: + "Present-day good intentions aren't sufficient to make the longterm future good in expectation", + author: 'trurl', + link: 'https://forum.effectivealtruism.org/posts/FBNk5ibcWwYcavkh4/present-day-good-intentions-aren-t-sufficient-to-make-the', + }, + { + title: + 'A podcast episode exploring critiques of effective altruism (with Michael Nielsen and Ajeya Cotra)', + author: 'spencerg', + link: 'https://forum.effectivealtruism.org/posts/2dHk3zBmmnNTefjWB/a-podcast-episode-exploring-critiques-of-effective-altruism', + }, + { + title: 'Follow-up: Crowdsourced Criticisms', + author: 'Hmash', + link: 'https://forum.effectivealtruism.org/posts/kXCsTDB5s7QRnWS8f/follow-up-crowdsourced-criticisms', + }, + { + title: 'Why the EA aversion to local altruistic action?', + author: 'Locke', + link: 'https://forum.effectivealtruism.org/posts/LnuuN7zuBSZvEo845/why-the-ea-aversion-to-local-altruistic-action', + }, + { + title: 'Effective Altruists and Religion: A Proposal for Experimentation', + author: 'Kbrown', + link: 'https://forum.effectivealtruism.org/posts/YA6fCNwB2c5cydrtG/effective-altruists-and-religion-a-proposal-for', + }, + { + title: + 'On the institutional critique of effective altruism: a response (mainly) to Brian Berkey ', + author: 'zzz1407', + link: 'https://forum.effectivealtruism.org/posts/GgNgnzjqceDghhozf/on-the-institutional-critique-of-effective-altruism-a-1', + }, + { + title: + 'We Can’t Do Long Term Utilitarian Calculations Until We Know if AIs Can Be Conscious or Not', + author: 'Mike20731', + link: 'https://forum.effectivealtruism.org/posts/Zsz3BYQTJjJdZd4DR/we-can-t-do-long-term-utilitarian-calculations-until-we-know', + }, + { + title: 'The ordinal utility argument against effective altruism ', + author: 'Barracuda', + link: 'https://forum.effectivealtruism.org/posts/rNYCcRLzkQtQEBnLa/the-ordinal-utility-argument-against-effective-altruism', + }, + { + title: + 'Reciprocity & the causes of diminishing returns: cause exploration submission', + link: 'https://forum.effectivealtruism.org/posts/x9towRLtvYidkXugk/reciprocity-and-the-causes-of-diminishing-returns-cause', + }, + { + title: + 'Altruism is systems change, so why isn’t EA? Constructive criticism.', + link: 'https://forum.effectivealtruism.org/posts/xZrvbwhSLmsGmHHSD/altruism-is-systems-change-so-why-isn-t-ea-constructive', + }, + { + title: 'The reasonableness of special concerns', + author: 'jwt', + link: 'https://forum.effectivealtruism.org/posts/CFGYLDgvsYQhsyZ42/the-reasonableness-of-special-concerns', + }, + { + title: 'The EA community should utilize the concept of beliefs more often', + author: 'Noah Scales', + link: 'https://forum.effectivealtruism.org/posts/9SKqeNSvAKozeMvGq/the-ea-community-should-utilize-the-concept-of-beliefs-more', + }, + { + title: 'Why bother doing the most good?', + author: 'Dov', + link: 'https://forum.effectivealtruism.org/posts/ZPcKeZbcC5SgLGLwg/why-bother-doing-the-most-good', + }, + { + title: + 'Framing EA as tending towards longtermism might be diminishing its potential impact', + author: 'Mm', + link: 'https://forum.effectivealtruism.org/posts/guGteQYvwcuDAECPA/framing-ea-as-tending-towards-longtermism-might-be', + }, + { + title: 'Bernard Williams: Ethics and the limits of impartiality', + author: 'peterhartree', + link: 'https://forum.effectivealtruism.org/posts/G6EWTrArPDf74sr3S/bernard-williams-ethics-and-the-limits-of-impartiality', + }, + { + title: 'Love and AI: Relational Brain/Mind Dynamics in AI Development', + author: 'JeffreyK', + link: 'https://forum.effectivealtruism.org/posts/MdfLn33GpNWGN7CSE/love-and-ai-relational-brain-mind-dynamics-in-ai-development', + }, + { + title: 'When 2/3rds of the world goes against you', + author: 'JeffreyK', + link: 'https://forum.effectivealtruism.org/posts/6va2EfHkQ3bTmdDyn/when-2-3rds-of-the-world-goes-against-you', + }, + { + title: 'My views on EA --> attempt to a constructive criticism', + author: 'Jin Jo', + link: 'https://forum.effectivealtruism.org/posts/LcDcqX6KWGHm3tSgr/my-views-on-ea-greater-than-attempt-to-a-constructive', + }, + { + title: 'Empirical critique of EA from another direction', + author: 'tonz', + link: 'https://forum.effectivealtruism.org/posts/nsqhmwmwZmWvFA2wb/empirical-critique-of-ea-from-another-direction', + }, + { + title: 'Critique: Cost-Benefit of Weirdness', + author: 'Mike Elias', + link: 'https://forum.effectivealtruism.org/posts/kw8ZmziAwcqPW2jt6/critique-cost-benefit-of-weirdness', + }, + { + title: 'Hits- or misses-based giving', + author: 'brb243', + link: 'https://forum.effectivealtruism.org/posts/XzawnaT4jyqpkEihz/hits-or-misses-based-giving', + }, + { + title: 'Mind your step', + author: 'Talsome', + link: 'https://forum.effectivealtruism.org/posts/rGNaz4GtWCzPbCWCB/mind-your-step', + }, + { + title: 'Against Impartial Altruism', + author: 'Sam K', + link: 'https://forum.effectivealtruism.org/posts/f5ZxK2k9gyZthHGND/against-impartial-altruism', + }, + { + title: 'Criticism of EA and longtermism', + author: 'St. Ignorant', + link: 'https://forum.effectivealtruism.org/posts/DuG8rBSAErSmSN7uE/criticism-of-ea-and-longtermism', + }, + { + title: + 'Against Longtermism: \nI welcome our robot overlords, and you should too!', + author: 'MattBall', + link: 'https://forum.effectivealtruism.org/posts/Cuu4Jjmp7QqL4a5Ls/against-longtermism-i-welcome-our-robot-overlords-and-you', + }, + { + title: 'Effective Altruism Criticisms', + author: 'Gavin Palmer (heroLFG.com)', + link: 'https://forum.effectivealtruism.org/posts/mMaAcvNLQPC3aTqB6/effective-altruism-criticisms', + }, + { + title: '"Of Human Bondage" and Morality', + author: 'Casaubon', + link: 'https://forum.effectivealtruism.org/posts/ZJnKCToBojYqqQphb/of-human-bondage-and-morality', + }, + { + title: + 'Portfolios, Locality, and Career - Three Critiques of Effective Altruism', + author: 'Philip Apps', + link: 'https://forum.effectivealtruism.org/posts/AoL2h2ZqTSNevdtRM/portfolios-locality-and-career-three-critiques-of-effective', + }, + { + title: 'Effective altruism in a non-ideal world', + author: 'Eric Kramer', + link: 'https://forum.effectivealtruism.org/posts/2nApcLJsZeABu38uW/effective-altruism-in-a-non-ideal-world', + }, + { + title: 'The future of humanity', + author: 'Dem0sthenes', + link: 'https://forum.effectivealtruism.org/posts/nLyG65eQepKKeGbrg/the-future-of-humanity', + }, + { + title: + 'Investigating Ideology: want to earn money, help EA and/or me? Then check this out; it may be a mighty neglected cause ', + author: 'Dov', + link: 'https://forum.effectivealtruism.org/posts/twaKWNjAc4KEz3kMq/investigating-ideology-want-to-earn-money-help-ea-and-or-me', + }, + { + title: 'Accepting the Inevitability of Ambitious Egoism (”AE”)', + author: 'Dem0sthenes', + link: 'https://forum.effectivealtruism.org/posts/bQsxsaEcvxzEML9ZW/accepting-the-inevitability-of-ambitious-egoism-ae', + }, + { + title: 'Book Review: What We Owe The Future (Erik Hoel)', + author: 'ErikHoel', + link: 'https://forum.effectivealtruism.org/posts/AyPTZLTwm5hN2Kfcb/book-review-what-we-owe-the-future-erik-hoel', + }, + { + title: + 'Effective Altruism Goes Political: Normative Conflicts and Practical Judgment', + author: 'Michael Haiden', + link: 'https://forum.effectivealtruism.org/posts/aisE9yhZHuiM9Cdn7/effective-altruism-goes-political-normative-conflicts-and-1', + }, + { + title: 'Values lock-in is already happening (without AGI)', + link: 'https://forum.effectivealtruism.org/posts/ogwD28mzJy8dkwtmc/values-lock-in-is-already-happening-without-agi', + }, + { + title: 'EA Should Rename Itself', + author: 'Name Rectifier', + link: 'https://forum.effectivealtruism.org/posts/swkxLtjG9z7RY7i9x/ea-should-rename-itself', + }, + { + title: 'What we are for? Community, Correction and Scale [wip]', + author: 'Nathan Young', + link: 'https://forum.effectivealtruism.org/posts/QCv5GNcQFeH34iN2w/what-we-are-for-community-correction-and-scale-wip', + }, + { + title: '“One should love one’s neighbor more than oneself.”', + author: 'Barracuda', + link: 'https://forum.effectivealtruism.org/posts/bxbu8v83gw3MDzCBX/one-should-love-one-s-neighbor-more-than-oneself', + }, + { + title: 'Run For President', + author: 'Brian Moore', + link: 'https://forum.effectivealtruism.org/posts/ZniCnE8XhCMLeGHj8/run-for-president', + }, + { + title: 'Effective Altruism Risks Perpetuating a Harmful Worldview', + author: 'Theo Cox', + link: 'https://forum.effectivealtruism.org/posts/QRaf9iWvGbfKgWBvY/effective-altruism-risks-perpetuating-a-harmful-worldview', + }, +] diff --git a/functions/src/scripts/contest/scrape-ea.ts b/functions/src/scripts/contest/scrape-ea.ts new file mode 100644 index 00000000..c22f4ac7 --- /dev/null +++ b/functions/src/scripts/contest/scrape-ea.ts @@ -0,0 +1,55 @@ +// Run with `npx ts-node src/scripts/contest/scrape-ea.ts` +import * as fs from 'fs' +import * as puppeteer from 'puppeteer' + +export function scrapeEA(contestLink: string, fileName: string) { + ;(async () => { + const browser = await puppeteer.launch({ headless: true }) + const page = await browser.newPage() + await page.goto(contestLink) + + let loadMoreButton = await page.$('.LoadMore-root') + + while (loadMoreButton) { + await loadMoreButton.click() + await page.waitForNetworkIdle() + loadMoreButton = await page.$('.LoadMore-root') + } + + /* Run javascript inside the page */ + const data = await page.evaluate(() => { + const list = [] + const items = document.querySelectorAll('.PostsItem2-root') + + for (const item of items) { + const link = + 'https://forum.effectivealtruism.org' + + item?.querySelector('a')?.getAttribute('href') + + // Replace '&' with '&' + const clean = (str: string | undefined) => str?.replace(/&/g, '&') + + list.push({ + title: clean(item?.querySelector('a>span>span')?.innerHTML), + author: item?.querySelector('a.UsersNameDisplay-userName')?.innerHTML, + link: link, + }) + } + + return list + }) + + fs.writeFileSync( + `./src/scripts/contest/${fileName}.ts`, + `export const data = ${JSON.stringify(data, null, 2)}` + ) + + console.log(data) + await browser.close() + })() +} + +scrapeEA( + 'https://forum.effectivealtruism.org/topics/criticism-and-red-teaming-contest', + 'criticism-and-red-teaming' +) diff --git a/yarn.lock b/yarn.lock index b03bbcca..9829f0b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3564,6 +3564,13 @@ dependencies: "@types/node" "*" +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@5.36.0": version "5.36.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.0.tgz#8f159c4cdb3084eb5d4b72619a2ded942aa109e5" @@ -4316,7 +4323,7 @@ base16@^1.0.0: resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== -base64-js@^1.3.0: +base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -4346,6 +4353,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.7.1: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -4459,6 +4475,11 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4 node-releases "^2.0.3" picocolors "^1.0.0" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -4469,6 +4490,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^5.2.1, buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -4648,6 +4677,11 @@ chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -5014,7 +5048,7 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-fetch@^3.1.5: +cross-fetch@3.1.5, cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -5336,7 +5370,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5492,6 +5526,11 @@ detective@^5.2.1: defined "^1.0.0" minimist "^1.2.6" +devtools-protocol@0.0.1036444: + version "0.0.1036444" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1036444.tgz#a570d3cdde61527c82f9b03919847b8ac7b1c2b9" + integrity sha512-0y4f/T8H9lsESV9kKP1HDUXgHxCdniFeJh6Erq+FbdOEvp/Ydp9t8kcAAM5gOd17pMrTDlFWntoHtzzeTUWKNw== + dicer@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.1.tgz#abf28921e3475bc5e801e74e0159fd94f927ba97" @@ -6232,6 +6271,17 @@ extend@^3.0.0, extend@^3.0.2, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -6314,6 +6364,13 @@ fbjs@^3.0.0, fbjs@^3.0.1: setimmediate "^1.0.5" ua-parser-js "^0.7.30" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + feed@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/feed/-/feed-4.2.2.tgz#865783ef6ed12579e2c44bbef3c9113bc4956a7e" @@ -6573,6 +6630,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^10.0.1: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -7291,6 +7353,14 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + https-proxy-agent@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81" @@ -7299,14 +7369,6 @@ https-proxy-agent@^3.0.0: agent-base "^4.3.0" debug "^3.1.0" -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -7329,6 +7391,11 @@ idb@7.0.1: resolved "https://registry.yarnpkg.com/idb/-/idb-7.0.1.tgz#d2875b3a2f205d854ee307f6d196f246fea590a7" integrity sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg== +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -7402,7 +7469,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -8557,6 +8624,11 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" @@ -9200,6 +9272,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -9622,6 +9699,11 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +progress@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -9812,7 +9894,7 @@ proxy-agent@^3.0.3: proxy-from-env "^1.0.0" socks-proxy-agent "^4.0.1" -proxy-from-env@^1.0.0: +proxy-from-env@1.1.0, proxy-from-env@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -9861,6 +9943,23 @@ pupa@^2.1.1: dependencies: escape-goat "^2.0.0" +puppeteer@18.0.5: + version "18.0.5" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-18.0.5.tgz#873223b17b92345182c5b5e8cfbd6f3117f1547d" + integrity sha512-s4erjxU0VtKojPvF+KvLKG6OHUPw7gO2YV1dtOsoryyCbhrs444fXb4QZqGWuTv3V/rgSCUzeixxu34g0ZkSMA== + dependencies: + cross-fetch "3.1.5" + debug "4.3.4" + devtools-protocol "0.0.1036444" + extract-zip "2.0.1" + https-proxy-agent "5.0.1" + progress "2.0.3" + proxy-from-env "1.1.0" + rimraf "3.0.2" + tar-fs "2.1.1" + unbzip2-stream "1.4.3" + ws "8.8.1" + pure-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" @@ -10241,7 +10340,7 @@ readable-stream@2, readable-stream@^2.0.1, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1: +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -11329,6 +11428,27 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + teeny-request@^7.1.3: version "7.2.0" resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.2.0.tgz#41347ece068f08d741e7b86df38a4498208b2633" @@ -11366,6 +11486,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + thunkify@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d" @@ -11589,6 +11714,14 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +unbzip2-stream@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -12196,6 +12329,11 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@8.8.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== + ws@>=7.4.6: version "8.6.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" @@ -12276,6 +12414,14 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" From c1c3a360fd9b2c20222a80630f6384ec70771efd Mon Sep 17 00:00:00 2001 From: Austin Chen <akrolsmir@gmail.com> Date: Sun, 25 Sep 2022 13:08:34 -0400 Subject: [PATCH 45/60] Add CART contest to /tournaments --- functions/src/scripts/contest/create-markets.ts | 5 +++-- web/pages/tournaments/index.tsx | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/functions/src/scripts/contest/create-markets.ts b/functions/src/scripts/contest/create-markets.ts index f0d4962c..ba7245fe 100644 --- a/functions/src/scripts/contest/create-markets.ts +++ b/functions/src/scripts/contest/create-markets.ts @@ -30,8 +30,9 @@ async function postMarket(submission: CEPSubmission) { initialProb: 10, // Super secret options: // groupId: 'y2hcaGybXT1UfobK3XTx', // [DEV] CEP Tournament - groupId: 'h3MhjYbSSG6HbxY8ZTwE', // [DEV] CART // groupId: 'cMcpBQ2p452jEcJD2SFw', // [PROD] Predict CEP + groupId: 'h3MhjYbSSG6HbxY8ZTwE', // [DEV] CART + // groupId: 'K86LmEmidMKdyCHdHNv4', // [PROD] CART visibility: 'unlisted', // TODO: Increase liquidity? }), @@ -41,7 +42,7 @@ async function postMarket(submission: CEPSubmission) { } async function postAll() { - for (const submission of data.slice(3, 6)) { + for (const submission of data.slice(0, 3)) { await postMarket(submission) } } diff --git a/web/pages/tournaments/index.tsx b/web/pages/tournaments/index.tsx index 8378b185..0b9dbc80 100644 --- a/web/pages/tournaments/index.tsx +++ b/web/pages/tournaments/index.tsx @@ -107,7 +107,14 @@ const tourneys: Tourney[] = [ groupId: 'SxGRqXRpV3RAQKudbcNb', }, - // Tournaments without awards get featured belows + // Tournaments without awards get featured below + { + title: 'Criticism and Red Teaming Contest', + blurb: + 'Which criticisms of Effective Altruism have been the most valuable?', + endTime: toDate('Sep 30, 2022'), + groupId: 'K86LmEmidMKdyCHdHNv4', + }, { title: 'SF 2022 Ballot', blurb: 'Which ballot initiatives will pass this year in SF and CA?', From be2c60d3f3a518909f3eef93af6f31f9e408e4ce Mon Sep 17 00:00:00 2001 From: Marshall Polaris <marshall@pol.rs> Date: Sun, 25 Sep 2022 16:43:53 -0700 Subject: [PATCH 46/60] Fix some rendering issues on contract page (#933) * Memoize calculating sale amount on your bets list * Don't re-render more than necessary with `useIsMobile` hook * Use `useIsMobile` hook in `AmountInput` --- web/components/amount-input.tsx | 5 ++--- web/components/bets-list.tsx | 22 ++++++++++++++-------- web/hooks/use-is-mobile.ts | 16 +++++++++++----- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/web/components/amount-input.tsx b/web/components/amount-input.tsx index 2ad745a8..76581d9e 100644 --- a/web/components/amount-input.tsx +++ b/web/components/amount-input.tsx @@ -5,7 +5,7 @@ import { formatMoney } from 'common/util/format' import { Col } from './layout/col' import { SiteLink } from './site-link' import { ENV_CONFIG } from 'common/envs/constants' -import { useWindowSize } from 'web/hooks/use-window-size' +import { useIsMobile } from 'web/hooks/use-is-mobile' export function AmountInput(props: { amount: number | undefined @@ -34,8 +34,7 @@ export function AmountInput(props: { const isInvalid = !str || isNaN(amount) onChange(isInvalid ? undefined : amount) } - const { width } = useWindowSize() - const isMobile = (width ?? 0) < 768 + const isMobile = useIsMobile(768) return ( <Col className={className}> <label className="input-group mb-4"> diff --git a/web/components/bets-list.tsx b/web/components/bets-list.tsx index 97d11758..74480de5 100644 --- a/web/components/bets-list.tsx +++ b/web/components/bets-list.tsx @@ -610,18 +610,24 @@ function BetRow(props: { const isNumeric = outcomeType === 'NUMERIC' const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC' - const saleAmount = saleBet?.sale?.amount + // calculateSaleAmount is very slow right now so that's why we memoized this + const payout = useMemo(() => { + const saleBetAmount = saleBet?.sale?.amount + if (saleBetAmount) { + return saleBetAmount + } else if (contract.isResolved) { + return resolvedPayout(contract, bet) + } else { + return calculateSaleAmount(contract, bet, unfilledBets) + } + }, [contract, bet, saleBet, unfilledBets]) const saleDisplay = isAnte ? ( 'ANTE' - ) : saleAmount !== undefined ? ( - <>{formatMoney(saleAmount)} (sold)</> + ) : saleBet ? ( + <>{formatMoney(payout)} (sold)</> ) : ( - formatMoney( - isResolved - ? resolvedPayout(contract, bet) - : calculateSaleAmount(contract, bet, unfilledBets) - ) + formatMoney(payout) ) const payoutIfChosenDisplay = diff --git a/web/hooks/use-is-mobile.ts b/web/hooks/use-is-mobile.ts index 9ce0133c..7e99a97d 100644 --- a/web/hooks/use-is-mobile.ts +++ b/web/hooks/use-is-mobile.ts @@ -1,7 +1,13 @@ -import { useWindowSize } from 'web/hooks/use-window-size' +import { useEffect, useState } from 'react' -// matches talwind sm breakpoint -export function useIsMobile() { - const { width } = useWindowSize() - return (width ?? 0) < 640 +export function useIsMobile(threshold?: number) { + const [isMobile, setIsMobile] = useState<boolean>() + useEffect(() => { + // 640 matches tailwind sm breakpoint + const onResize = () => setIsMobile(window.innerWidth < (threshold ?? 640)) + onResize() + window.addEventListener('resize', onResize) + return () => window.removeEventListener('resize', onResize) + }, [threshold]) + return isMobile } From 68120ec2b2f01a8d687626d7cf29dc3a3e5268b5 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Sun, 25 Sep 2022 23:29:13 -0400 Subject: [PATCH 47/60] Revert "Clean up and fix stuff on answers panel (#914)" This reverts commit 721448f40811889cb8780f7c1ea5c537fbbc4fb1. --- web/components/answers/answers-panel.tsx | 41 ++++++++++++++++-------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/web/components/answers/answers-panel.tsx b/web/components/answers/answers-panel.tsx index 51cf5799..a1cef4c3 100644 --- a/web/components/answers/answers-panel.tsx +++ b/web/components/answers/answers-panel.tsx @@ -38,13 +38,26 @@ export function AnswersPanel(props: { const answers = (useAnswers(contract.id) ?? contract.answers).filter( (a) => a.number != 0 || contract.outcomeType === 'MULTIPLE_CHOICE' ) - const [winningAnswers, notWinningAnswers] = partition( - answers, - (a) => a.id === resolution || (resolutions && resolutions[a.id]) + const hasZeroBetAnswers = answers.some((answer) => totalBets[answer.id] < 1) + + const [winningAnswers, losingAnswers] = partition( + answers.filter((a) => (showAllAnswers ? true : totalBets[a.id] > 0)), + (answer) => + answer.id === resolution || (resolutions && resolutions[answer.id]) ) - const [visibleAnswers, invisibleAnswers] = partition( - sortBy(notWinningAnswers, (a) => -getOutcomeProbability(contract, a.id)), - (a) => showAllAnswers || totalBets[a.id] > 0 + const sortedAnswers = [ + ...sortBy(winningAnswers, (answer) => + resolutions ? -1 * resolutions[answer.id] : 0 + ), + ...sortBy( + resolution ? [] : losingAnswers, + (answer) => -1 * getDpmOutcomeProbability(contract.totalShares, answer.id) + ), + ] + + const answerItems = sortBy( + losingAnswers.length > 0 ? losingAnswers : sortedAnswers, + (answer) => -getOutcomeProbability(contract, answer.id) ) const user = useUser() @@ -94,13 +107,13 @@ export function AnswersPanel(props: { return ( <Col className="gap-3"> {(resolveOption || resolution) && - sortBy(winningAnswers, (a) => -(resolutions?.[a.id] ?? 0)).map((a) => ( + sortedAnswers.map((answer) => ( <AnswerItem - key={a.id} - answer={a} + key={answer.id} + answer={answer} contract={contract} showChoice={showChoice} - chosenProb={chosenAnswers[a.id]} + chosenProb={chosenAnswers[answer.id]} totalChosenProb={chosenTotal} onChoose={onChoose} onDeselect={onDeselect} @@ -114,10 +127,10 @@ export function AnswersPanel(props: { tradingAllowed(contract) ? '' : '-mb-6' )} > - {visibleAnswers.map((a) => ( - <OpenAnswer key={a.id} answer={a} contract={contract} /> + {answerItems.map((item) => ( + <OpenAnswer key={item.id} answer={item} contract={contract} /> ))} - {invisibleAnswers.length > 0 && !showAllAnswers && ( + {hasZeroBetAnswers && !showAllAnswers && ( <Button className="self-end" color="gray-white" @@ -130,7 +143,7 @@ export function AnswersPanel(props: { </Col> )} - {answers.length === 0 && ( + {answers.length <= 1 && ( <div className="pb-4 text-gray-500">No answers yet...</div> )} From bf92c4fb0680a1bd9595d4ba4a614d4e187f348d Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Mon, 26 Sep 2022 11:28:54 -0400 Subject: [PATCH 48/60] Fix 500 on non-existant group page --- web/pages/group/[...slugs]/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/pages/group/[...slugs]/index.tsx b/web/pages/group/[...slugs]/index.tsx index bed244eb..a23ce602 100644 --- a/web/pages/group/[...slugs]/index.tsx +++ b/web/pages/group/[...slugs]/index.tsx @@ -122,7 +122,7 @@ const groupSubpages = [ export default function GroupPage(props: { group: Group | null memberIds: string[] - creator: User + creator: User | null topTraders: { user: User; score: number }[] topCreators: { user: User; score: number }[] messages: GroupComment[] @@ -163,11 +163,11 @@ export default function GroupPage(props: { const memberIds = useMemberIds(group?.id ?? null) ?? props.memberIds useSaveReferral(user, { - defaultReferrerUsername: creator.username, + defaultReferrerUsername: creator?.username, groupId: group?.id, }) - if (group === null || !groupSubpages.includes(page) || slugs[2]) { + if (group === null || !groupSubpages.includes(page) || slugs[2] || !creator) { return <Custom404 /> } const isCreator = user && group && user.id === group.creatorId From d9292f7a95b8c209c5538976353697ca6e73a68f Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Mon, 26 Sep 2022 11:30:41 -0400 Subject: [PATCH 49/60] Switch order of my groups and all tabs --- web/pages/groups.tsx | 52 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/web/pages/groups.tsx b/web/pages/groups.tsx index 49d99d18..d5c73913 100644 --- a/web/pages/groups.tsx +++ b/web/pages/groups.tsx @@ -102,6 +102,32 @@ export default function Groups(props: { className="mb-4" currentPageForAnalytics={'groups'} tabs={[ + { + title: 'All', + content: ( + <Col> + <input + type="text" + onChange={(e) => debouncedQuery(e.target.value)} + placeholder="Search groups" + value={query} + className="input input-bordered mb-4 w-full" + /> + + <div className="flex flex-wrap justify-center gap-4"> + {matchesOrderedByMostContractAndMembers.map((group) => ( + <GroupCard + key={group.id} + group={group} + creator={creatorsDict[group.creatorId]} + user={user} + isMember={memberGroupIds.includes(group.id)} + /> + ))} + </div> + </Col> + ), + }, ...(user ? [ { @@ -136,32 +162,6 @@ export default function Groups(props: { }, ] : []), - { - title: 'All', - content: ( - <Col> - <input - type="text" - onChange={(e) => debouncedQuery(e.target.value)} - placeholder="Search groups" - value={query} - className="input input-bordered mb-4 w-full" - /> - - <div className="flex flex-wrap justify-center gap-4"> - {matchesOrderedByMostContractAndMembers.map((group) => ( - <GroupCard - key={group.id} - group={group} - creator={creatorsDict[group.creatorId]} - user={user} - isMember={memberGroupIds.includes(group.id)} - /> - ))} - </div> - </Col> - ), - }, ]} /> </Col> From cc3b44891bc1e4a6abfcc215850af43bce0d0f17 Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Mon, 26 Sep 2022 15:56:47 -0400 Subject: [PATCH 50/60] Add user to market followers in create answer --- functions/src/create-answer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/functions/src/create-answer.ts b/functions/src/create-answer.ts index cc05d817..911f3b8c 100644 --- a/functions/src/create-answer.ts +++ b/functions/src/create-answer.ts @@ -7,6 +7,7 @@ import { getNewMultiBetInfo } from '../../common/new-bet' import { Answer, MAX_ANSWER_LENGTH } from '../../common/answer' import { getValues } from './utils' import { APIError, newEndpoint, validate } from './api' +import { addUserToContractFollowers } from './follow-market' const bodySchema = z.object({ contractId: z.string().max(MAX_ANSWER_LENGTH), @@ -96,6 +97,8 @@ export const createanswer = newEndpoint(opts, async (req, auth) => { return answer }) + await addUserToContractFollowers(contractId, auth.uid) + return answer }) From a10e4c115e3c16ce9490f6bde3d95083904429a0 Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Mon, 26 Sep 2022 15:57:21 -0400 Subject: [PATCH 51/60] Fix dpm MULTI resolution payouts bug --- common/payouts-dpm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/payouts-dpm.ts b/common/payouts-dpm.ts index bf6f5ebc..48850dca 100644 --- a/common/payouts-dpm.ts +++ b/common/payouts-dpm.ts @@ -168,7 +168,7 @@ export const getPayoutsMultiOutcome = ( const winnings = (shares / sharesByOutcome[outcome]) * prob * poolTotal const profit = winnings - amount - const payout = amount + (1 - DPM_FEES) * Math.max(0, profit) + const payout = amount + (1 - DPM_FEES) * profit return { userId, profit, payout } }) From 94ffac287e141c949a262fb4782a052ff5e931be Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Mon, 26 Sep 2022 15:57:38 -0400 Subject: [PATCH 52/60] Payout resolution notifications styling --- web/pages/notifications.tsx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/web/pages/notifications.tsx b/web/pages/notifications.tsx index 907157f9..4f9700dd 100644 --- a/web/pages/notifications.tsx +++ b/web/pages/notifications.tsx @@ -971,6 +971,8 @@ function ContractResolvedNotification(props: { const { sourceText, data } = notification const { userInvestment, userPayout } = (data as ContractResolutionData) ?? {} const subtitle = 'resolved the market' + const profitable = userPayout >= userInvestment + const ROI = (userPayout - userInvestment) / userInvestment const resolutionDescription = () => { if (!sourceText) return <div /> @@ -1002,23 +1004,21 @@ function ContractResolvedNotification(props: { const description = userInvestment && userPayout !== undefined ? ( - <Row className={'gap-1 '}> - Resolved: {resolutionDescription()} - Invested: + <> + Resolved: {resolutionDescription()} Invested: <span className={'text-primary'}>{formatMoney(userInvestment)} </span> Payout: <span className={clsx( - userPayout > 0 ? 'text-primary' : 'text-red-500', - 'truncate' + profitable ? 'text-primary' : 'text-red-500', + 'truncate text-ellipsis' )} > {formatMoney(userPayout)} - {` (${userPayout > 0 ? '+' : ''}${Math.round( - ((userPayout - userInvestment) / userInvestment) * 100 - )}%)`} + {userPayout > 0 && + ` (${profitable ? '+' : ''}${Math.round(ROI * 100)}%)`} </span> - </Row> + </> ) : ( <span>Resolved {resolutionDescription()}</span> ) @@ -1038,9 +1038,7 @@ function ContractResolvedNotification(props: { highlighted={highlighted} subtitle={subtitle} > - <Row> - <span>{description}</span> - </Row> + <Row className={'line-clamp-2 space-x-1'}>{description}</Row> </NotificationFrame> ) } From 90eaf83775dbe20dca26ecfd3bced7b7769420cd Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Mon, 26 Sep 2022 17:04:08 -0400 Subject: [PATCH 53/60] Redirect from '/home' to '/' if not logged in --- web/pages/home/index.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index fda80c50..b42b37bb 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -55,6 +55,13 @@ export default function Home() { useSaveReferral() usePrefetch(user?.id) + useEffect(() => { + if (user === null) { + // Go to landing page if not logged in. + Router.push('/') + } + }) + const groups = useMemberGroupsSubscription(user) const { sections } = getHomeItems(groups ?? [], user?.homeSections ?? []) From 2ef025a151cc81293153551d0f56e35371c57c14 Mon Sep 17 00:00:00 2001 From: James Grugett <jahooma@gmail.com> Date: Mon, 26 Sep 2022 17:43:27 -0400 Subject: [PATCH 54/60] Only set daily score on contracts that are at least day old --- functions/src/score-contracts.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/functions/src/score-contracts.ts b/functions/src/score-contracts.ts index 52ef39d4..497a4ba0 100644 --- a/functions/src/score-contracts.ts +++ b/functions/src/score-contracts.ts @@ -5,6 +5,7 @@ import { Bet } from '../../common/bet' import { Contract } from '../../common/contract' import { log } from './utils' import { removeUndefinedProps } from '../../common/util/object' +import { DAY_MS, HOUR_MS } from '../../common/util/time' export const scoreContracts = functions .runWith({ memory: '4GB', timeoutSeconds: 540 }) @@ -16,11 +17,12 @@ const firestore = admin.firestore() async function scoreContractsInternal() { const now = Date.now() - const lastHour = now - 60 * 60 * 1000 - const last3Days = now - 1000 * 60 * 60 * 24 * 3 + const hourAgo = now - HOUR_MS + const dayAgo = now - DAY_MS + const threeDaysAgo = now - DAY_MS * 3 const activeContractsSnap = await firestore .collection('contracts') - .where('lastUpdatedTime', '>', lastHour) + .where('lastUpdatedTime', '>', hourAgo) .get() const activeContracts = activeContractsSnap.docs.map( (doc) => doc.data() as Contract @@ -41,15 +43,21 @@ async function scoreContractsInternal() { for (const contract of contracts) { const bets = await firestore .collection(`contracts/${contract.id}/bets`) - .where('createdTime', '>', last3Days) + .where('createdTime', '>', threeDaysAgo) .get() const bettors = bets.docs .map((doc) => doc.data() as Bet) .map((bet) => bet.userId) const popularityScore = uniq(bettors).length + const wasCreatedToday = contract.createdTime > dayAgo + let dailyScore: number | undefined - if (contract.outcomeType === 'BINARY' && contract.mechanism === 'cpmm-1') { + if ( + contract.outcomeType === 'BINARY' && + contract.mechanism === 'cpmm-1' && + !wasCreatedToday + ) { const percentChange = Math.abs(contract.probChanges.day) dailyScore = popularityScore * percentChange } From df316fc4dabc9ae837eb0eb97d0ded8da7679a1a Mon Sep 17 00:00:00 2001 From: Ian Philips <iansphilips@gmail.com> Date: Mon, 26 Sep 2022 17:49:06 -0400 Subject: [PATCH 55/60] Portfolio update emails (#928) * Stats computing correctly * Styles propagating - testing in prod now * Formatting html * Reset portfolio flag on mondays at 12am * Add profit, styling * More styling, less reports * Cleanup * Comments * comment * Try to send higher signal emails * Send emails to proper email address --- common/calculate-metrics.ts | 19 + common/user.ts | 1 + .../weekly-portfolio-update-no-movers.html | 411 ++++++++++++++ .../weekly-portfolio-update.html | 510 ++++++++++++++++++ functions/src/emails.ts | 95 +++- functions/src/index.ts | 1 + functions/src/reset-weekly-emails-flag.ts | 1 + functions/src/serve.ts | 2 + functions/src/test-scheduled-function.ts | 17 + functions/src/utils.ts | 4 + functions/src/weekly-portfolio-emails.ts | 280 ++++++++++ 11 files changed, 1316 insertions(+), 25 deletions(-) create mode 100644 functions/src/email-templates/weekly-portfolio-update-no-movers.html create mode 100644 functions/src/email-templates/weekly-portfolio-update.html create mode 100644 functions/src/test-scheduled-function.ts create mode 100644 functions/src/weekly-portfolio-emails.ts diff --git a/common/calculate-metrics.ts b/common/calculate-metrics.ts index b27ac977..7c2153c1 100644 --- a/common/calculate-metrics.ts +++ b/common/calculate-metrics.ts @@ -21,6 +21,25 @@ const computeInvestmentValue = ( }) } +export const computeInvestmentValueCustomProb = ( + bets: Bet[], + contract: Contract, + p: number +) => { + return sumBy(bets, (bet) => { + if (!contract || contract.isResolved) return 0 + if (bet.sale || bet.isSold) return 0 + const { outcome, shares } = bet + + const betP = outcome === 'YES' ? p : 1 - p + + const payout = betP * shares + const value = payout - (bet.loanAmount ?? 0) + if (isNaN(value)) return 0 + return value + }) +} + const computeTotalPool = (userContracts: Contract[], startTime = 0) => { const periodFilteredContracts = userContracts.filter( (contract) => contract.createdTime >= startTime diff --git a/common/user.ts b/common/user.ts index 0372d99b..b1365929 100644 --- a/common/user.ts +++ b/common/user.ts @@ -57,6 +57,7 @@ export type PrivateUser = { email?: string weeklyTrendingEmailSent?: boolean + weeklyPortfolioUpdateEmailSent?: boolean manaBonusEmailSent?: boolean initialDeviceToken?: string initialIpAddress?: string diff --git a/functions/src/email-templates/weekly-portfolio-update-no-movers.html b/functions/src/email-templates/weekly-portfolio-update-no-movers.html new file mode 100644 index 00000000..15303992 --- /dev/null +++ b/functions/src/email-templates/weekly-portfolio-update-no-movers.html @@ -0,0 +1,411 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" + xmlns:o="urn:schemas-microsoft-com:office:office"> + +<head> + <title>Weekly Portfolio Update on Manifold + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + +
+ + + + + + + + + + + +
+ + + + + + + +
+ + + + banner logo + + + +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + +
+
+

+ Hi {{name}},

+
+
+
+

+ + We ran the numbers and here's how you did this past week! + +

+
+
+ Profit +
+

+ {{profit}} +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ 🔥 Prediction streak + + {{prediction_streak}} +
+ 💸 Tips received + + {{tips_received}} +
+ 📈 Markets traded + + {{markets_traded}} +
+ ❓ Markets created + + {{markets_created}} +
+ 🥳 Traders attracted + + {{unique_bettors}} +
+ +
+
+
+
+ + +
+ + + + + + +
+ + +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + +
+
+

+ This e-mail has been sent to + {{name}}, + click here to unsubscribe from this type of notification. +

+
+
+
+
+ +
+
+ +
+
\ No newline at end of file diff --git a/functions/src/email-templates/weekly-portfolio-update.html b/functions/src/email-templates/weekly-portfolio-update.html new file mode 100644 index 00000000..fd99837f --- /dev/null +++ b/functions/src/email-templates/weekly-portfolio-update.html @@ -0,0 +1,510 @@ + + + + + Weekly Portfolio Update on Manifold + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + +
+ + + + + + + + + + + +
+ + + + + + + +
+ + + + banner logo + + + +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ Hi {{name}},

+
+
+
+

+ + We ran the numbers and here's how you did this past week! + +

+
+
+ Profit +
+

+ {{profit}} +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ 🔥 Prediction streak + + {{prediction_streak}} +
+ 💸 Tips received + + {{tips_received}} +
+ 📈 Markets traded + + {{markets_traded}} +
+ ❓ Markets created + + {{markets_created}} +
+ 🥳 Traders attracted + + {{unique_bettors}} +
+ +
+
+

+ + And here's some of the biggest changes in your portfolio: + +

+
+
+ + + + + + + + + + + + + + + + + + +
+ + {{question1Title}} + + + +

+ {{question1Prob}} + +

+ {{question1Change}} + +

+

+
+ + {{question2Title}} + + + +

+ {{question2Prob}} + +

+ {{question2Change}} + +

+

+
+ + {{question3Title}} + + + +

+ {{question3Prob}} + +

+ {{question3Change}} + +

+

+
+ + {{question4Title}} + + + +

+ {{question4Prob}} + +

+ {{question4Change}} + +

+

+
+ +
+
+
+
+ + +
+ + + + + + +
+ + +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + +
+
+

+ This e-mail has been sent to + {{name}}, + click here to unsubscribe from this type of notification. +

+
+
+
+
+ +
+
+ +
+
diff --git a/functions/src/emails.ts b/functions/src/emails.ts index 98309ebe..dd91789a 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -12,14 +12,15 @@ import { getValueFromBucket } from '../../common/calculate-dpm' import { formatNumericProbability } from '../../common/pseudo-numeric' import { sendTemplateEmail, sendTextEmail } from './send-email' -import { getUser } from './utils' +import { contractUrl, getUser } from './utils' import { buildCardUrl, getOpenGraphProps } from '../../common/contract-details' import { notification_reason_types } from '../../common/notification' import { Dictionary } from 'lodash' +import { getNotificationDestinationsForUser } from '../../common/user-notification-preferences' import { - getNotificationDestinationsForUser, - notification_preference, -} from '../../common/user-notification-preferences' + PerContractInvestmentsData, + OverallPerformanceData, +} from 'functions/src/weekly-portfolio-emails' export const sendMarketResolutionEmail = async ( reason: notification_reason_types, @@ -152,9 +153,10 @@ export const sendWelcomeEmail = async ( const { name } = user const firstName = name.split(' ')[0] - const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${ - 'onboarding_flow' as notification_preference - }` + const { unsubscribeUrl } = getNotificationDestinationsForUser( + privateUser, + 'onboarding_flow' + ) return await sendTemplateEmail( privateUser.email, @@ -220,9 +222,11 @@ export const sendOneWeekBonusEmail = async ( const { name } = user const firstName = name.split(' ')[0] - const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${ - 'onboarding_flow' as notification_preference - }` + const { unsubscribeUrl } = getNotificationDestinationsForUser( + privateUser, + 'onboarding_flow' + ) + return await sendTemplateEmail( privateUser.email, 'Manifold Markets one week anniversary gift', @@ -252,10 +256,10 @@ export const sendCreatorGuideEmail = async ( const { name } = user const firstName = name.split(' ')[0] - - const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${ - 'onboarding_flow' as notification_preference - }` + const { unsubscribeUrl } = getNotificationDestinationsForUser( + privateUser, + 'onboarding_flow' + ) return await sendTemplateEmail( privateUser.email, 'Create your own prediction market', @@ -286,10 +290,10 @@ export const sendThankYouEmail = async ( const { name } = user const firstName = name.split(' ')[0] - - const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${ - 'thank_you_for_purchases' as notification_preference - }` + const { unsubscribeUrl } = getNotificationDestinationsForUser( + privateUser, + 'thank_you_for_purchases' + ) return await sendTemplateEmail( privateUser.email, @@ -469,9 +473,10 @@ export const sendInterestingMarketsEmail = async ( ) return - const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${ - 'trending_markets' as notification_preference - }` + const { unsubscribeUrl } = getNotificationDestinationsForUser( + privateUser, + 'trending_markets' + ) const { name } = user const firstName = name.split(' ')[0] @@ -507,10 +512,6 @@ export const sendInterestingMarketsEmail = async ( ) } -function contractUrl(contract: Contract) { - return `https://manifold.markets/${contract.creatorUsername}/${contract.slug}` -} - function imageSourceUrl(contract: Contract) { return buildCardUrl(getOpenGraphProps(contract)) } @@ -612,3 +613,47 @@ export const sendNewUniqueBettorsEmail = async ( } ) } + +export const sendWeeklyPortfolioUpdateEmail = async ( + user: User, + privateUser: PrivateUser, + investments: PerContractInvestmentsData[], + overallPerformance: OverallPerformanceData +) => { + if ( + !privateUser || + !privateUser.email || + !privateUser.notificationPreferences.profit_loss_updates.includes('email') + ) + return + + const { unsubscribeUrl } = getNotificationDestinationsForUser( + privateUser, + 'profit_loss_updates' + ) + + const { name } = user + const firstName = name.split(' ')[0] + const templateData: Record = { + name: firstName, + unsubscribeUrl, + ...overallPerformance, + } + investments.forEach((investment, i) => { + templateData[`question${i + 1}Title`] = investment.questionTitle + templateData[`question${i + 1}Url`] = investment.questionUrl + templateData[`question${i + 1}Prob`] = investment.questionProb + templateData[`question${i + 1}Change`] = investment.questionChange + templateData[`question${i + 1}ChangeStyle`] = investment.questionChangeStyle + }) + + await sendTemplateEmail( + privateUser.email, + // 'iansphilips@gmail.com', + `Here's your weekly portfolio update!`, + investments.length === 0 + ? 'portfolio-update-no-movers' + : 'portfolio-update', + templateData + ) +} diff --git a/functions/src/index.ts b/functions/src/index.ts index 2cb6f515..4844cea8 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -30,6 +30,7 @@ export * from './reset-betting-streaks' export * from './reset-weekly-emails-flag' export * from './on-update-contract-follow' export * from './on-update-like' +export * from './weekly-portfolio-emails' // v2 export * from './health' diff --git a/functions/src/reset-weekly-emails-flag.ts b/functions/src/reset-weekly-emails-flag.ts index 947e3e88..9a769498 100644 --- a/functions/src/reset-weekly-emails-flag.ts +++ b/functions/src/reset-weekly-emails-flag.ts @@ -17,6 +17,7 @@ export const resetWeeklyEmailsFlag = functions privateUsers.map(async (user) => { return firestore.collection('private-users').doc(user.id).update({ weeklyTrendingEmailSent: false, + weeklyPortfolioEmailSent: false, }) }) ) diff --git a/functions/src/serve.ts b/functions/src/serve.ts index 6d062d40..99ac6281 100644 --- a/functions/src/serve.ts +++ b/functions/src/serve.ts @@ -28,6 +28,7 @@ import { stripewebhook, createcheckoutsession } from './stripe' import { getcurrentuser } from './get-current-user' import { createpost } from './create-post' import { savetwitchcredentials } from './save-twitch-credentials' +import { testscheduledfunction } from './test-scheduled-function' type Middleware = (req: Request, res: Response, next: NextFunction) => void const app = express() @@ -69,6 +70,7 @@ addJsonEndpointRoute('/getcurrentuser', getcurrentuser) addJsonEndpointRoute('/savetwitchcredentials', savetwitchcredentials) addEndpointRoute('/stripewebhook', stripewebhook, express.raw()) addEndpointRoute('/createpost', createpost) +addEndpointRoute('/testscheduledfunction', testscheduledfunction) app.listen(PORT) console.log(`Serving functions on port ${PORT}.`) diff --git a/functions/src/test-scheduled-function.ts b/functions/src/test-scheduled-function.ts new file mode 100644 index 00000000..41aa9fe9 --- /dev/null +++ b/functions/src/test-scheduled-function.ts @@ -0,0 +1,17 @@ +import { APIError, newEndpoint } from './api' +import { sendPortfolioUpdateEmailsToAllUsers } from './weekly-portfolio-emails' +import { isProd } from './utils' + +// Function for testing scheduled functions locally +export const testscheduledfunction = newEndpoint( + { method: 'GET', memory: '4GiB' }, + async (_req) => { + if (isProd()) + throw new APIError(400, 'This function is only available in dev mode') + + // Replace your function here + await sendPortfolioUpdateEmailsToAllUsers() + + return { success: true } + } +) diff --git a/functions/src/utils.ts b/functions/src/utils.ts index 6bb8349a..efc22e53 100644 --- a/functions/src/utils.ts +++ b/functions/src/utils.ts @@ -170,3 +170,7 @@ export const chargeUser = ( export const getContractPath = (contract: Contract) => { return `/${contract.creatorUsername}/${contract.slug}` } + +export function contractUrl(contract: Contract) { + return `https://manifold.markets/${contract.creatorUsername}/${contract.slug}` +} diff --git a/functions/src/weekly-portfolio-emails.ts b/functions/src/weekly-portfolio-emails.ts new file mode 100644 index 00000000..dcbb68dd --- /dev/null +++ b/functions/src/weekly-portfolio-emails.ts @@ -0,0 +1,280 @@ +import * as functions from 'firebase-functions' +import * as admin from 'firebase-admin' + +import { Contract, CPMMContract } from '../../common/contract' +import { + getAllPrivateUsers, + getPrivateUser, + getUser, + getValue, + getValues, + isProd, + log, +} from './utils' +import { filterDefined } from '../../common/util/array' +import { DAY_MS } from '../../common/util/time' +import { partition, sortBy, sum, uniq } from 'lodash' +import { Bet } from '../../common/bet' +import { computeInvestmentValueCustomProb } from '../../common/calculate-metrics' +import { sendWeeklyPortfolioUpdateEmail } from './emails' +import { contractUrl } from './utils' +import { Txn } from '../../common/txn' +import { formatMoney } from '../../common/util/format' + +// TODO: reset weeklyPortfolioUpdateEmailSent to false for all users at the start of each week +export const weeklyPortfolioUpdateEmails = functions + .runWith({ secrets: ['MAILGUN_KEY'], memory: '4GB' }) + // every minute on Friday for an hour at 12pm PT (UTC -07:00) + .pubsub.schedule('* 19 * * 5') + .timeZone('Etc/UTC') + .onRun(async () => { + await sendPortfolioUpdateEmailsToAllUsers() + }) + +const firestore = admin.firestore() + +export async function sendPortfolioUpdateEmailsToAllUsers() { + const privateUsers = isProd() + ? // ian & stephen's ids + // ? filterDefined([ + // await getPrivateUser('AJwLWoo3xue32XIiAVrL5SyR1WB2'), + // await getPrivateUser('tlmGNz9kjXc2EteizMORes4qvWl2'), + // ]) + await getAllPrivateUsers() + : filterDefined([await getPrivateUser('6hHpzvRG0pMq8PNJs7RZj2qlZGn2')]) + // get all users that haven't unsubscribed from weekly emails + const privateUsersToSendEmailsTo = privateUsers + .filter((user) => { + return isProd() + ? user.notificationPreferences.profit_loss_updates.includes('email') && + !user.weeklyPortfolioUpdateEmailSent + : true + }) + // Send emails in batches + .slice(0, 200) + log( + 'Sending weekly portfolio emails to', + privateUsersToSendEmailsTo.length, + 'users' + ) + + const usersBets: { [userId: string]: Bet[] } = {} + // get all bets made by each user + await Promise.all( + privateUsersToSendEmailsTo.map(async (user) => { + return getValues( + firestore.collectionGroup('bets').where('userId', '==', user.id) + ).then((bets) => { + usersBets[user.id] = bets + }) + }) + ) + + const usersToContractsCreated: { [userId: string]: Contract[] } = {} + // Get all contracts created by each user + await Promise.all( + privateUsersToSendEmailsTo.map(async (user) => { + return getValues( + firestore + .collection('contracts') + .where('creatorId', '==', user.id) + .where('createdTime', '>', Date.now() - 7 * DAY_MS) + ).then((contracts) => { + usersToContractsCreated[user.id] = contracts + }) + }) + ) + + // Get all txns the users received over the past week + const usersToTxnsReceived: { [userId: string]: Txn[] } = {} + await Promise.all( + privateUsersToSendEmailsTo.map(async (user) => { + return getValues( + firestore + .collection(`txns`) + .where('toId', '==', user.id) + .where('createdTime', '>', Date.now() - 7 * DAY_MS) + ).then((txn) => { + usersToTxnsReceived[user.id] = txn + }) + }) + ) + + // Get a flat map of all the bets that users made to get the contracts they bet on + const contractsUsersBetOn = filterDefined( + await Promise.all( + uniq( + Object.values(usersBets).flatMap((bets) => + bets.map((bet) => bet.contractId) + ) + ).map((contractId) => + getValue(firestore.collection('contracts').doc(contractId)) + ) + ) + ) + log('Found', contractsUsersBetOn.length, 'contracts') + let count = 0 + await Promise.all( + privateUsersToSendEmailsTo.map(async (privateUser) => { + const user = await getUser(privateUser.id) + if (!user) return + const userBets = usersBets[privateUser.id] as Bet[] + const contractsUserBetOn = contractsUsersBetOn.filter((contract) => + userBets.some((bet) => bet.contractId === contract.id) + ) + const contractsBetOnInLastWeek = uniq( + userBets + .filter((bet) => bet.createdTime > Date.now() - 7 * DAY_MS) + .map((bet) => bet.contractId) + ) + const totalTips = sum( + usersToTxnsReceived[privateUser.id] + .filter((txn) => txn.category === 'TIP') + .map((txn) => txn.amount) + ) + const greenBg = 'rgba(0,160,0,0.2)' + const redBg = 'rgba(160,0,0,0.2)' + const clearBg = 'rgba(255,255,255,0)' + const roundedProfit = + Math.round(user.profitCached.weekly) === 0 + ? 0 + : Math.floor(user.profitCached.weekly) + const performanceData = { + profit: formatMoney(user.profitCached.weekly), + profit_style: `background-color: ${ + roundedProfit > 0 ? greenBg : roundedProfit === 0 ? clearBg : redBg + }`, + markets_created: + usersToContractsCreated[privateUser.id].length.toString(), + tips_received: formatMoney(totalTips), + unique_bettors: usersToTxnsReceived[privateUser.id] + .filter((txn) => txn.category === 'UNIQUE_BETTOR_BONUS') + .length.toString(), + markets_traded: contractsBetOnInLastWeek.length.toString(), + prediction_streak: + (user.currentBettingStreak?.toString() ?? '0') + ' days', + // More options: bonuses, tips given, + } as OverallPerformanceData + + const investmentValueDifferences = sortBy( + filterDefined( + contractsUserBetOn.map((contract) => { + const cpmmContract = contract as CPMMContract + if (cpmmContract === undefined || cpmmContract.prob === undefined) + return + const bets = userBets.filter( + (bet) => bet.contractId === contract.id + ) + + const marketProbabilityAWeekAgo = + cpmmContract.prob - cpmmContract.probChanges.week + const currentMarketProbability = cpmmContract.resolutionProbability + ? cpmmContract.resolutionProbability + : cpmmContract.prob + const betsValueAWeekAgo = computeInvestmentValueCustomProb( + bets.filter((b) => b.createdTime < Date.now() - 7 * DAY_MS), + contract, + marketProbabilityAWeekAgo + ) + const currentBetsValue = computeInvestmentValueCustomProb( + bets, + contract, + currentMarketProbability + ) + const marketChange = + currentMarketProbability - marketProbabilityAWeekAgo + return { + currentValue: currentBetsValue, + pastValue: betsValueAWeekAgo, + difference: currentBetsValue - betsValueAWeekAgo, + contractSlug: contract.slug, + marketProbAWeekAgo: marketProbabilityAWeekAgo, + questionTitle: contract.question, + questionUrl: contractUrl(contract), + questionProb: cpmmContract.resolution + ? cpmmContract.resolution + : Math.round(cpmmContract.prob * 100) + '%', + questionChange: + (marketChange > 0 ? '+' : '') + + Math.round(marketChange * 100) + + '%', + questionChangeStyle: `color: ${ + currentMarketProbability > marketProbabilityAWeekAgo + ? 'rgba(0,160,0,1)' + : '#a80000' + };`, + } as PerContractInvestmentsData + }) + ), + (differences) => Math.abs(differences.difference) + ).reverse() + + log( + 'Found', + investmentValueDifferences.length, + 'investment differences for user', + privateUser.id + ) + + const [winningInvestments, losingInvestments] = partition( + investmentValueDifferences.filter( + (diff) => + diff.pastValue > 0.01 && + Math.abs(diff.difference / diff.pastValue) > 0.01 // difference is greater than 1% + ), + (investmentsData: PerContractInvestmentsData) => { + return investmentsData.difference > 0 + } + ) + // pick 3 winning investments and 3 losing investments + const topInvestments = winningInvestments.slice(0, 2) + const worstInvestments = losingInvestments.slice(0, 2) + // if no bets in the last week ANd no market movers AND no markets created, don't send email + if ( + contractsBetOnInLastWeek.length === 0 && + topInvestments.length === 0 && + worstInvestments.length === 0 && + usersToContractsCreated[privateUser.id].length === 0 + ) { + log('No bets in last week, no market movers, no markets created') + await firestore.collection('private-users').doc(privateUser.id).update({ + weeklyPortfolioUpdateEmailSent: true, + }) + return + } + await sendWeeklyPortfolioUpdateEmail( + user, + privateUser, + topInvestments.concat(worstInvestments) as PerContractInvestmentsData[], + performanceData + ) + await firestore.collection('private-users').doc(privateUser.id).update({ + weeklyPortfolioUpdateEmailSent: true, + }) + log('Sent weekly portfolio update email to', privateUser.email) + count++ + log('sent out emails to user count:', count) + }) + ) +} + +export type PerContractInvestmentsData = { + questionTitle: string + questionUrl: string + questionProb: string + questionChange: string + questionChangeStyle: string + currentValue: number + pastValue: number + difference: number +} + +export type OverallPerformanceData = { + profit: string + prediction_streak: string + markets_traded: string + profit_style: string + tips_received: string + markets_created: string + unique_bettors: string +} From f7bf42d2e0cdcf0ab9f6d2bb4681d8660ccaaf45 Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Mon, 26 Sep 2022 17:54:48 -0400 Subject: [PATCH 56/60] Rename & correct spelling --- functions/src/index.ts | 2 +- ...set-weekly-emails-flag.ts => reset-weekly-emails-flags.ts} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename functions/src/{reset-weekly-emails-flag.ts => reset-weekly-emails-flags.ts} (87%) diff --git a/functions/src/index.ts b/functions/src/index.ts index 4844cea8..9a8ec232 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -27,7 +27,7 @@ export * from './on-delete-group' export * from './score-contracts' export * from './weekly-markets-emails' export * from './reset-betting-streaks' -export * from './reset-weekly-emails-flag' +export * from './reset-weekly-emails-flags' export * from './on-update-contract-follow' export * from './on-update-like' export * from './weekly-portfolio-emails' diff --git a/functions/src/reset-weekly-emails-flag.ts b/functions/src/reset-weekly-emails-flags.ts similarity index 87% rename from functions/src/reset-weekly-emails-flag.ts rename to functions/src/reset-weekly-emails-flags.ts index 9a769498..1b2109a1 100644 --- a/functions/src/reset-weekly-emails-flag.ts +++ b/functions/src/reset-weekly-emails-flags.ts @@ -2,7 +2,7 @@ import * as functions from 'firebase-functions' import * as admin from 'firebase-admin' import { getAllPrivateUsers } from './utils' -export const resetWeeklyEmailsFlag = functions +export const resetWeeklyEmailsFlags = functions .runWith({ timeoutSeconds: 300, memory: '4GB', @@ -17,7 +17,7 @@ export const resetWeeklyEmailsFlag = functions privateUsers.map(async (user) => { return firestore.collection('private-users').doc(user.id).update({ weeklyTrendingEmailSent: false, - weeklyPortfolioEmailSent: false, + weeklyPortfolioUpdateEmailSent: false, }) }) ) From 3ed3b6fb4281f05f21a60aa1709cc446e7d4198c Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Mon, 26 Sep 2022 18:05:50 -0400 Subject: [PATCH 57/60] Set email sent flag if skipped over --- functions/src/weekly-markets-emails.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/functions/src/weekly-markets-emails.ts b/functions/src/weekly-markets-emails.ts index bec5949c..7c6f21a4 100644 --- a/functions/src/weekly-markets-emails.ts +++ b/functions/src/weekly-markets-emails.ts @@ -46,12 +46,14 @@ async function sendTrendingMarketsEmailsToAllUsers() { ? await getAllPrivateUsers() : filterDefined([await getPrivateUser('6hHpzvRG0pMq8PNJs7RZj2qlZGn2')]) // get all users that haven't unsubscribed from weekly emails - const privateUsersToSendEmailsTo = privateUsers.filter((user) => { - return ( - user.notificationPreferences.trending_markets.includes('email') && - !user.weeklyTrendingEmailSent - ) - }) + const privateUsersToSendEmailsTo = privateUsers + .filter((user) => { + return ( + user.notificationPreferences.trending_markets.includes('email') && + !user.weeklyTrendingEmailSent + ) + }) + .slice(150) // Send the emails out in batches log( 'Sending weekly trending emails to', privateUsersToSendEmailsTo.length, @@ -74,6 +76,7 @@ async function sendTrendingMarketsEmailsToAllUsers() { trendingContracts.map((c) => c.question).join('\n ') ) + // TODO: convert to Promise.all for (const privateUser of privateUsersToSendEmailsTo) { if (!privateUser.email) { log(`No email for ${privateUser.username}`) @@ -84,6 +87,9 @@ async function sendTrendingMarketsEmailsToAllUsers() { }) if (contractsAvailableToSend.length < numContractsToSend) { log('not enough new, unbet-on contracts to send to user', privateUser.id) + await firestore.collection('private-users').doc(privateUser.id).update({ + weeklyTrendingEmailSent: true, + }) continue } // choose random subset of contracts to send to user From 1b9811ce28e21a3e34379d5b63f2e4efd8a7656a Mon Sep 17 00:00:00 2001 From: SirSaltyy Date: Mon, 26 Sep 2022 18:12:24 -0400 Subject: [PATCH 58/60] Update twitch page copy --- web/pages/twitch.tsx | 53 +++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/web/pages/twitch.tsx b/web/pages/twitch.tsx index 22d3152d..6508a69e 100644 --- a/web/pages/twitch.tsx +++ b/web/pages/twitch.tsx @@ -146,7 +146,8 @@ function TwitchPlaysManifoldMarkets(props: {
Instead of Twitch channel points we use our own play money, mana (M$). All viewers start with M$1,000 and can earn more for free by betting - well. + well. Just like channel points, mana cannot be converted to real + money.
@@ -176,35 +177,47 @@ function TwitchChatCommands() { + - - - - + +
+ +
+ We recommend streamers sharing the link to the control dock with their + mods. Alternatively, chat commands can be used to control markets.{' '} +
+ +
@@ -384,8 +397,8 @@ function SetUpBot(props: { buttonOnClick={copyOverlayLink} > Create a new browser source in your streaming software such as OBS. - Paste in the above link and resize it to your liking. We recommend - setting the size to 400x400. + Paste in the above link and type in the desired size. We recommend + 450x375.
+
+ Need help? Contact SirSalty#5770 in Discord or email + david@manifold.markets +
) From d612192109f98251ea674e95fb8c33b0ccab243a Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Mon, 26 Sep 2022 18:13:15 -0400 Subject: [PATCH 59/60] Send market close notifs for each close time --- functions/src/market-close-notifications.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/src/market-close-notifications.ts b/functions/src/market-close-notifications.ts index 7878e410..21b52fbc 100644 --- a/functions/src/market-close-notifications.ts +++ b/functions/src/market-close-notifications.ts @@ -60,7 +60,7 @@ async function sendMarketCloseEmails() { 'contract', 'closed', user, - 'closed' + contract.id.slice(6, contract.id.length), + contract.id + '-closed-at-' + contract.closeTime, contract.closeTime?.toString() ?? new Date().toString(), { contract } ) From 2fe9fe593dea6f6b1e58689c4850f615eef79e3e Mon Sep 17 00:00:00 2001 From: ingawei <46611122+ingawei@users.noreply.github.com> Date: Mon, 26 Sep 2022 18:01:13 -0500 Subject: [PATCH 60/60] Inga/profile (#937) - Changed edit profile button - got rid of banner - merged stats and trades tab on profile - made multicolored profit graph --- web/components/bets-list.tsx | 39 +- web/components/contract-search.tsx | 6 + web/components/contract/contracts-grid.tsx | 1 + web/components/following-button.tsx | 16 +- web/components/groups/groups-button.tsx | 6 +- web/components/layout/tabs.tsx | 7 +- .../portfolio/portfolio-value-graph.tsx | 135 +++++- .../portfolio/portfolio-value-section.tsx | 169 +++++-- web/components/profile/user-likes-button.tsx | 6 +- web/components/referrals-button.tsx | 10 +- web/components/user-page.tsx | 449 +++++++++--------- web/pages/profile.tsx | 22 - 12 files changed, 529 insertions(+), 337 deletions(-) diff --git a/web/components/bets-list.tsx b/web/components/bets-list.tsx index 74480de5..dbb2db56 100644 --- a/web/components/bets-list.tsx +++ b/web/components/bets-list.tsx @@ -77,7 +77,7 @@ export function BetsList(props: { user: User }) { }, [contractList]) const [sort, setSort] = useState('newest') - const [filter, setFilter] = useState('open') + const [filter, setFilter] = useState('all') const [page, setPage] = useState(0) const start = page * CONTRACTS_PER_PAGE const end = start + CONTRACTS_PER_PAGE @@ -155,34 +155,25 @@ export function BetsList(props: { user: User }) { (c) => contractsMetrics[c.id].netPayout ) - const totalPnl = user.profitCached.allTime - const totalProfitPercent = (totalPnl / user.totalDeposits) * 100 const investedProfitPercent = ((currentBetsValue - currentInvested) / (currentInvested + 0.1)) * 100 return ( - - - -
Investment value
-
- {formatMoney(currentNetInvestment)}{' '} - -
- - -
Total profit
-
- {formatMoney(totalPnl)}{' '} - -
- -
+ + +
+ Investment value +
+
+ {formatMoney(currentNetInvestment)}{' '} + +
+ - + - + {displayedContracts.length === 0 ? ( diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index 331dcb80..ba589d0e 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -103,6 +103,7 @@ export function ContractSearch(props: { loadMore: () => void ) => ReactNode autoFocus?: boolean + profile?: boolean | undefined }) { const { user, @@ -123,6 +124,7 @@ export function ContractSearch(props: { maxResults, renderContracts, autoFocus, + profile, } = props const [state, setState] = usePersistentState( @@ -239,6 +241,10 @@ export function ContractSearch(props: { /> {renderContracts ? ( renderContracts(renderedContracts, performQuery) + ) : renderedContracts && renderedContracts.length === 0 && profile ? ( +

+ This creator does not yet have any markets. +

) : ( ) } diff --git a/web/components/following-button.tsx b/web/components/following-button.tsx index 135f43a8..c897c89b 100644 --- a/web/components/following-button.tsx +++ b/web/components/following-button.tsx @@ -13,16 +13,18 @@ import { useDiscoverUsers } from 'web/hooks/use-users' import { TextButton } from './text-button' import { track } from 'web/lib/service/analytics' -export function FollowingButton(props: { user: User }) { - const { user } = props +export function FollowingButton(props: { user: User; className?: string }) { + const { user, className } = props const [isOpen, setIsOpen] = useState(false) const followingIds = useFollows(user.id) const followerIds = useFollowers(user.id) return ( <> - setIsOpen(true)}> - {followingIds?.length ?? ''}{' '} + setIsOpen(true)} className={className}> + + {followingIds?.length ?? ''} + {' '} Following @@ -69,15 +71,15 @@ export function EditFollowingButton(props: { user: User; className?: string }) { ) } -export function FollowersButton(props: { user: User }) { - const { user } = props +export function FollowersButton(props: { user: User; className?: string }) { + const { user, className } = props const [isOpen, setIsOpen] = useState(false) const followingIds = useFollows(user.id) const followerIds = useFollowers(user.id) return ( <> - setIsOpen(true)}> + setIsOpen(true)} className={className}> {followerIds?.length ?? ''}{' '} Followers diff --git a/web/components/groups/groups-button.tsx b/web/components/groups/groups-button.tsx index e6271466..5c9d2edd 100644 --- a/web/components/groups/groups-button.tsx +++ b/web/components/groups/groups-button.tsx @@ -14,14 +14,14 @@ import { firebaseLogin } from 'web/lib/firebase/users' import { GroupLinkItem } from 'web/pages/groups' import toast from 'react-hot-toast' -export function GroupsButton(props: { user: User }) { - const { user } = props +export function GroupsButton(props: { user: User; className?: string }) { + const { user, className } = props const [isOpen, setIsOpen] = useState(false) const groups = useMemberGroups(user.id) return ( <> - setIsOpen(true)}> + setIsOpen(true)} className={className}> {groups?.length ?? ''} Groups diff --git a/web/components/layout/tabs.tsx b/web/components/layout/tabs.tsx index 980a3cfc..b82131ec 100644 --- a/web/components/layout/tabs.tsx +++ b/web/components/layout/tabs.tsx @@ -2,6 +2,7 @@ import clsx from 'clsx' import { useRouter, NextRouter } from 'next/router' import { ReactNode, useState } from 'react' import { track } from '@amplitude/analytics-browser' +import { Col } from './col' type Tab = { title: string @@ -55,11 +56,13 @@ export function ControlledTabs(props: TabProps & { activeIndex: number }) { )} aria-current={activeIndex === i ? 'page' : undefined} > - {tab.tabIcon && {tab.tabIcon}} {tab.badge ? ( {tab.badge} ) : null} - {tab.title} + + {tab.tabIcon &&
{tab.tabIcon}
} + {tab.title} + ))} diff --git a/web/components/portfolio/portfolio-value-graph.tsx b/web/components/portfolio/portfolio-value-graph.tsx index d8489b47..6ed5d195 100644 --- a/web/components/portfolio/portfolio-value-graph.tsx +++ b/web/components/portfolio/portfolio-value-graph.tsx @@ -1,72 +1,155 @@ import { ResponsiveLine } from '@nivo/line' import { PortfolioMetrics } from 'common/user' +import { filterDefined } from 'common/util/array' import { formatMoney } from 'common/util/format' +import dayjs from 'dayjs' import { last } from 'lodash' import { memo } from 'react' import { useWindowSize } from 'web/hooks/use-window-size' -import { formatTime } from 'web/lib/util/time' +import { Col } from '../layout/col' export const PortfolioValueGraph = memo(function PortfolioValueGraph(props: { portfolioHistory: PortfolioMetrics[] mode: 'value' | 'profit' + handleGraphDisplayChange: (arg0: string | number | null) => void height?: number - includeTime?: boolean }) { - const { portfolioHistory, height, includeTime, mode } = props + const { portfolioHistory, height, mode, handleGraphDisplayChange } = props const { width } = useWindowSize() - const points = portfolioHistory.map((p) => { - const { timestamp, balance, investmentValue, totalDeposits } = p - const value = balance + investmentValue - const profit = value - totalDeposits + const valuePoints = getPoints('value', portfolioHistory) + const posProfitPoints = getPoints('posProfit', portfolioHistory) + const negProfitPoints = getPoints('negProfit', portfolioHistory) + + const valuePointsY = valuePoints.map((p) => p.y) + const posProfitPointsY = posProfitPoints.map((p) => p.y) + const negProfitPointsY = negProfitPoints.map((p) => p.y) + + let data + + if (mode === 'value') { + data = [{ id: 'value', data: valuePoints, color: '#4f46e5' }] + } else { + data = [ + { + id: 'negProfit', + data: negProfitPoints, + color: '#dc2626', + }, + { + id: 'posProfit', + data: posProfitPoints, + color: '#14b8a6', + }, + ] + } + const numYTickValues = 2 + const endDate = last(data[0].data)?.x + + const yMin = + mode === 'value' + ? Math.min(...filterDefined(valuePointsY)) + : Math.min( + ...filterDefined(negProfitPointsY), + ...filterDefined(posProfitPointsY) + ) + + const yMax = + mode === 'value' + ? Math.max(...filterDefined(valuePointsY)) + : Math.max( + ...filterDefined(negProfitPointsY), + ...filterDefined(posProfitPointsY) + ) - return { - x: new Date(timestamp), - y: mode === 'value' ? value : profit, - } - }) - const data = [{ id: 'Value', data: points, color: '#11b981' }] - const numXTickValues = !width || width < 800 ? 2 : 5 - const numYTickValues = 4 - const endDate = last(points)?.x return (
= 800 ? 350 : 250) }} + style={{ height: height ?? (!width || width >= 800 ? 200 : 100) }} + onMouseLeave={() => handleGraphDisplayChange(null)} > p.y)), + min: yMin, + max: yMax, }} - gridYValues={numYTickValues} curve="stepAfter" enablePoints={false} colors={{ datum: 'color' }} axisBottom={{ - tickValues: numXTickValues, - format: (time) => formatTime(+time, !!includeTime), + tickValues: 0, }} pointBorderColor="#fff" - pointSize={points.length > 100 ? 0 : 6} + pointSize={valuePoints.length > 100 ? 0 : 6} axisLeft={{ tickValues: numYTickValues, - format: (value) => formatMoney(value), + format: '.3s', }} - enableGridX={!!width && width >= 800} + enableGridX={false} enableGridY={true} + gridYValues={numYTickValues} enableSlices="x" animate={false} yFormat={(value) => formatMoney(+value)} + enableArea={true} + areaOpacity={0.1} + sliceTooltip={({ slice }) => { + handleGraphDisplayChange(slice.points[0].data.yFormatted) + return ( +
+
+ +
+ {dayjs(slice.points[0].data.xFormatted).format('MMM/D/YY')} +
+
+ {dayjs(slice.points[0].data.xFormatted).format('h:mm A')} +
+ +
+ {/* ))} */} +
+ ) + }} >
) }) + +export function getPoints( + line: 'value' | 'posProfit' | 'negProfit', + portfolioHistory: PortfolioMetrics[] +) { + const points = portfolioHistory.map((p) => { + const { timestamp, balance, investmentValue, totalDeposits } = p + const value = balance + investmentValue + + const profit = value - totalDeposits + let posProfit = null + let negProfit = null + if (profit < 0) { + negProfit = profit + } else { + posProfit = profit + } + + return { + x: new Date(timestamp), + y: + line === 'value' ? value : line === 'posProfit' ? posProfit : negProfit, + } + }) + return points +} diff --git a/web/components/portfolio/portfolio-value-section.tsx b/web/components/portfolio/portfolio-value-section.tsx index a0006c60..ec364c8d 100644 --- a/web/components/portfolio/portfolio-value-section.tsx +++ b/web/components/portfolio/portfolio-value-section.tsx @@ -1,11 +1,12 @@ +import clsx from 'clsx' import { formatMoney } from 'common/util/format' import { last } from 'lodash' import { memo, useRef, useState } from 'react' import { usePortfolioHistory } from 'web/hooks/use-portfolio-history' import { Period } from 'web/lib/firebase/users' +import { PillButton } from '../buttons/pill-button' import { Col } from '../layout/col' import { Row } from '../layout/row' -import { Spacer } from '../layout/spacer' import { PortfolioValueGraph } from './portfolio-value-graph' export const PortfolioValueSection = memo( @@ -14,6 +15,13 @@ export const PortfolioValueSection = memo( const [portfolioPeriod, setPortfolioPeriod] = useState('weekly') const portfolioHistory = usePortfolioHistory(userId, portfolioPeriod) + const [graphMode, setGraphMode] = useState<'profit' | 'value'>('value') + const [graphDisplayNumber, setGraphDisplayNumber] = useState< + number | string | null + >(null) + const handleGraphDisplayChange = (num: string | number | null) => { + setGraphDisplayNumber(num) + } // Remember the last defined portfolio history. const portfolioRef = useRef(portfolioHistory) @@ -28,43 +36,144 @@ export const PortfolioValueSection = memo( const { balance, investmentValue, totalDeposits } = lastPortfolioMetrics const totalValue = balance + investmentValue const totalProfit = totalValue - totalDeposits - return ( <> - - -
Profit
-
{formatMoney(totalProfit)}
- - + + + setGraphMode('value')} + > +
+ Portfolio value +
+
+ {graphMode === 'value' + ? graphDisplayNumber + ? graphDisplayNumber + : formatMoney(totalValue) + : formatMoney(totalValue)} +
+ + setGraphMode('profit')} + > +
Profit
+
0 + ? 'text-teal-500' + : 'text-red-600' + : totalProfit > 0 + ? 'text-teal-500' + : 'text-red-600', + 'text-lg sm:text-xl' + )} + > + {graphMode === 'profit' + ? graphDisplayNumber + ? graphDisplayNumber + : formatMoney(totalProfit) + : formatMoney(totalProfit)} +
+ +
- - -
Portfolio value
-
{formatMoney(totalValue)}
- - ) } ) + +export function PortfolioPeriodSelection(props: { + setPortfolioPeriod: (string: any) => void + portfolioPeriod: string + className?: string + selectClassName?: string +}) { + const { setPortfolioPeriod, portfolioPeriod, className, selectClassName } = + props + return ( + + + + + + + ) +} + +export function GraphToggle(props: { + setGraphMode: (mode: 'profit' | 'value') => void + graphMode: string +}) { + const { setGraphMode, graphMode } = props + return ( + + { + setGraphMode('value') + }} + xs={true} + className="z-50" + > + Value + + { + setGraphMode('profit') + }} + xs={true} + className="z-50" + > + Profit + + + ) +} diff --git a/web/components/profile/user-likes-button.tsx b/web/components/profile/user-likes-button.tsx index 3d4fa9ac..666036a8 100644 --- a/web/components/profile/user-likes-button.tsx +++ b/web/components/profile/user-likes-button.tsx @@ -10,15 +10,15 @@ import { XIcon } from '@heroicons/react/outline' import { unLikeContract } from 'web/lib/firebase/likes' import { contractPath } from 'web/lib/firebase/contracts' -export function UserLikesButton(props: { user: User }) { - const { user } = props +export function UserLikesButton(props: { user: User; className?: string }) { + const { user, className } = props const [isOpen, setIsOpen] = useState(false) const likedContracts = useUserLikedContracts(user.id) return ( <> - setIsOpen(true)}> + setIsOpen(true)} className={className}> {likedContracts?.length ?? ''}{' '} Likes diff --git a/web/components/referrals-button.tsx b/web/components/referrals-button.tsx index b164e10c..9a548031 100644 --- a/web/components/referrals-button.tsx +++ b/web/components/referrals-button.tsx @@ -13,14 +13,18 @@ import { getUser, updateUser } from 'web/lib/firebase/users' import { TextButton } from 'web/components/text-button' import { UserLink } from 'web/components/user-link' -export function ReferralsButton(props: { user: User; currentUser?: User }) { - const { user, currentUser } = props +export function ReferralsButton(props: { + user: User + currentUser?: User + className?: string +}) { + const { user, currentUser, className } = props const [isOpen, setIsOpen] = useState(false) const referralIds = useReferrals(user.id) return ( <> - setIsOpen(true)}> + setIsOpen(true)} className={className}> {referralIds?.length ?? ''}{' '} Referrals diff --git a/web/components/user-page.tsx b/web/components/user-page.tsx index f9845fbe..bcbb395e 100644 --- a/web/components/user-page.tsx +++ b/web/components/user-page.tsx @@ -1,8 +1,13 @@ import clsx from 'clsx' import { useEffect, useState } from 'react' -import { useRouter } from 'next/router' +import { NextRouter, useRouter } from 'next/router' import { LinkIcon } from '@heroicons/react/solid' -import { PencilIcon } from '@heroicons/react/outline' +import { + ChatIcon, + FolderIcon, + PencilIcon, + ScaleIcon, +} from '@heroicons/react/outline' import { User } from 'web/lib/firebase/users' import { useUser } from 'web/hooks/use-user' @@ -24,39 +29,23 @@ import { FollowersButton, FollowingButton } from './following-button' import { UserFollowButton } from './follow-button' import { GroupsButton } from 'web/components/groups/groups-button' import { PortfolioValueSection } from './portfolio/portfolio-value-section' -import { ReferralsButton } from 'web/components/referrals-button' import { formatMoney } from 'common/util/format' -import { ShareIconButton } from 'web/components/share-icon-button' -import { ENV_CONFIG } from 'common/envs/constants' import { BettingStreakModal, hasCompletedStreakToday, } from 'web/components/profile/betting-streak-modal' -import { REFERRAL_AMOUNT } from 'common/economy' import { LoansModal } from './profile/loans-modal' -import { UserLikesButton } from 'web/components/profile/user-likes-button' -import { PAST_BETS } from 'common/user' -import { capitalize } from 'lodash' export function UserPage(props: { user: User }) { const { user } = props const router = useRouter() const currentUser = useUser() const isCurrentUser = user.id === currentUser?.id - const bannerUrl = user.bannerUrl ?? defaultBannerUrl(user.id) const [showConfetti, setShowConfetti] = useState(false) - const [showBettingStreakModal, setShowBettingStreakModal] = useState(false) - const [showLoansModal, setShowLoansModal] = useState(false) useEffect(() => { const claimedMana = router.query['claimed-mana'] === 'yes' - const showBettingStreak = router.query['show'] === 'betting-streak' - setShowBettingStreakModal(showBettingStreak) - setShowConfetti(claimedMana || showBettingStreak) - - const showLoansModel = router.query['show'] === 'loans' - setShowLoansModal(showLoansModel) - + setShowConfetti(claimedMana) const query = { ...router.query } if (query.claimedMana || query.show) { delete query['claimed-mana'] @@ -85,218 +74,159 @@ export function UserPage(props: { user: User }) { {showConfetti && ( )} - - {showLoansModal && ( - - )} - {/* Banner image up top, with an circle avatar overlaid */} -
-
-
+ + -
- - {/* Top right buttons (e.g. edit, follow) */} -
- {!isCurrentUser && } {isCurrentUser && ( - - {' '} -
Edit
-
+
+ + {' '} + +
)} -
-
- {/* Profile details: name, username, bio, and link to twitter/discord */} - - - - - {user.name} - - @{user.username} - - - - - = 0 ? 'text-green-600' : 'text-red-400' - )} - > - {formatMoney(profit)} + +
+ + + {user.name} - profit - - setShowBettingStreakModal(true)} - > - 🔥 {user.currentBettingStreak ?? 0} - streak - - setShowLoansModal(true)} - > - - 🏦 {formatMoney(user.nextLoanCached ?? 0)} + + @{user.username} - next loan - + {isCurrentUser && ( + + )} + {!isCurrentUser && } +
+
- - {user.bio && ( - <> -
- -
- - - )} - {(user.website || user.twitterHandle || user.discordHandle) && ( - - {user.website && ( - - - - {user.website} - - - )} - - {user.twitterHandle && ( - - - Twitter - - {user.twitterHandle} - - - - )} - - {user.discordHandle && ( - - - Discord - - {user.discordHandle} - - - - )} - - )} - {currentUser?.id === user.id && REFERRAL_AMOUNT > 0 && ( - - - - Earn {formatMoney(REFERRAL_AMOUNT)} when you refer a friend! - {' '} - You've gotten{' '} - - - - - )} - - ), - }, - { - title: 'Comments', - content: ( - - - - ), - }, - { - title: capitalize(PAST_BETS), - content: ( - <> - - - ), - }, - { - title: 'Stats', - content: ( - - - - - - - + + + + + {user.bio && ( + <> +
+ +
+ + + )} + {(user.website || user.twitterHandle || user.discordHandle) && ( + + {user.website && ( + + + + + {user.website} + - - - ), - }, - ]} - /> + + )} + + {user.twitterHandle && ( + + + Twitter + + {user.twitterHandle} + + + + )} + + {user.discordHandle && ( + + + Discord + + {user.discordHandle} + + + + )} + + )} + , + content: ( + <> + + + + + + ), + }, + { + title: 'Markets', + tabIcon: , + content: ( + <> + + + + ), + }, + { + title: 'Comments', + tabIcon: , + content: ( + <> + + + + + + ), + }, + ]} + /> + ) @@ -314,3 +244,88 @@ export function defaultBannerUrl(userId: string) { ] return defaultBanner[genHash(userId)() % defaultBanner.length] } + +export function ProfilePrivateStats(props: { + currentUser: User | null | undefined + profit: number + user: User + router: NextRouter +}) { + const { currentUser, profit, user, router } = props + const [showBettingStreakModal, setShowBettingStreakModal] = useState(false) + const [showLoansModal, setShowLoansModal] = useState(false) + + useEffect(() => { + const showBettingStreak = router.query['show'] === 'betting-streak' + setShowBettingStreakModal(showBettingStreak) + + const showLoansModel = router.query['show'] === 'loans' + setShowLoansModal(showLoansModel) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + return ( + <> + + + = 0 ? 'text-green-600' : 'text-red-400')} + > + {formatMoney(profit)} + + profit + + setShowBettingStreakModal(true)} + > + + 🔥 {user.currentBettingStreak ?? 0} + + + streak + + + setShowLoansModal(true)} + > + + 🏦 {formatMoney(user.nextLoanCached ?? 0)} + + next loan + + + {BettingStreakModal && ( + + )} + {showLoansModal && ( + + )} + + ) +} + +export function ProfilePublicStats(props: { user: User; className?: string }) { + const { user, className } = props + return ( + + + + {/* */} + + {/* */} + + ) +} diff --git a/web/pages/profile.tsx b/web/pages/profile.tsx index 2c095db6..caa9f47a 100644 --- a/web/pages/profile.tsx +++ b/web/pages/profile.tsx @@ -13,7 +13,6 @@ import { Page } from 'web/components/page' import { SEO } from 'web/components/SEO' import { SiteLink } from 'web/components/site-link' import { Title } from 'web/components/title' -import { defaultBannerUrl } from 'web/components/user-page' import { generateNewApiKey } from 'web/lib/api/api-key' import { changeUserInfo } from 'web/lib/firebase/api' import { redirectIfLoggedOut } from 'web/lib/firebase/server-auth' @@ -176,27 +175,6 @@ export default function ProfilePage(props: { onBlur={updateUsername} /> - - {/* TODO: Allow users with M$ 2000 of assets to set custom banners */} - {/* */} - -
- {( [ ['bio', 'Bio'],