From e2f5e11a6d31893401a1112ddc07a9ab4a7e3b31 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 14:04:06 -0800 Subject: [PATCH 01/14] site activity --- web/components/site-activity.tsx | 275 +++++++++++++++++++++++++++++++ web/pages/activity.tsx | 31 ++++ 2 files changed, 306 insertions(+) create mode 100644 web/components/site-activity.tsx create mode 100644 web/pages/activity.tsx diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx new file mode 100644 index 0000000000..21b68ba827 --- /dev/null +++ b/web/components/site-activity.tsx @@ -0,0 +1,275 @@ +import clsx from 'clsx' +import { ContractComment } from 'common/comment' +import { Contract } from 'common/contract' +import { filterDefined } from 'common/util/array' +import { + groupBy, + keyBy, + orderBy, + partition, + range, + sortBy, + uniq, + uniqBy, +} from 'lodash' +import { memo } from 'react' +import { useBetsOnce, useSubscribeGlobalBets } from 'web/hooks/use-bets' +import { + useGlobalComments, + useSubscribeGlobalComments, +} from 'web/hooks/use-comments' +import { + usePublicContracts, + useLiveAllNewContracts, +} from 'web/hooks/use-contract' +import { usePrivateUser } from 'web/hooks/use-user' +import { ContractMention } from './contract/contract-mention' +import { FeedBet } from './feed/feed-bets' +import { Col } from './layout/col' +import { Row } from './layout/row' +import { RelativeTimestamp } from './relative-timestamp' +import { Avatar } from './widgets/avatar' +import { Content } from './widgets/editor' +import { LoadingIndicator } from './widgets/loading-indicator' +import { UserLink } from './widgets/user-link' +import { UserHovercard } from './user/user-hovercard' +import { Bet } from 'common/bet' + +const filterBets = (bet: Bet, contract: Contract | undefined) => + bet.amount >= 500 || (contract?.token === 'CASH' && bet.amount >= 5) + +const filterComments = ( + comment: ContractComment, + contract: Contract | undefined +) => (comment.likes ?? 0) - (comment.dislikes ?? 0) >= 2 + +const filterNewContracts = (contract: Contract) => + contract.marketTier !== 'play' + +const count = 50 + +export function SiteActivity(props: { + className?: string + blockedUserIds?: string[] +}) { + const { className } = props + + const privateUser = usePrivateUser() + + const blockedGroupSlugs = privateUser?.blockedGroupSlugs ?? [] + const blockedContractIds = privateUser?.blockedContractIds ?? [] + const blockedUserIds = (privateUser?.blockedUserIds ?? []).concat( + props.blockedUserIds ?? [] + ) + + const recentBets = useBetsOnce({ + limit: count * 3, + filterRedemptions: true, + order: 'desc', + }) + const allRealtimeBets = useSubscribeGlobalBets({ + filterRedemptions: true, + }) + const realtimeBets = sortBy(allRealtimeBets, 'createdTime') + .reverse() + .slice(0, count * 3) + + const recentComments = useGlobalComments(count * 3) + const realtimeComments = useSubscribeGlobalComments() + + const newContracts = useLiveAllNewContracts(count * 3)?.filter( + (c) => + !blockedContractIds.includes(c.id) && + !blockedUserIds.includes(c.creatorId) && + c.visibility === 'public' && + (!c.groupSlugs?.some((slug) => blockedGroupSlugs.includes(slug)) || true) + ) + const bets = uniqBy( + [...(realtimeBets ?? []), ...(recentBets ?? [])], + 'id' + ).filter( + (bet) => + !blockedContractIds.includes(bet.contractId) && + !blockedUserIds.includes(bet.userId) + ) + const comments = uniqBy( + [...(realtimeComments ?? []), ...(recentComments ?? [])], + 'id' + ).filter( + (c) => + c.commentType === 'contract' && + !blockedContractIds.includes(c.contractId) && + !blockedUserIds.includes(c.userId) + ) + + const activeContractIds = uniq([ + ...bets.map((b) => b.contractId), + ...comments.map((c) => c.contractId), + ]) + + const activeContracts = usePublicContracts( + activeContractIds, + undefined, + blockedGroupSlugs + ) + + const [contracts, _unlistedContracts] = partition( + filterDefined(activeContracts ?? []).concat(newContracts ?? []), + (c) => c.visibility === 'public' + ) + const contractsById = keyBy(contracts, 'id') + + const displayedBets = bets.filter((bet) => + filterBets(bet, contractsById[bet.contractId]) + ) + + const displayedComments = comments.filter((comment) => + filterComments(comment, contractsById[comment.contractId]) + ) + + const displayedNewContracts = newContracts?.filter(filterNewContracts) + + const items = sortBy( + [...displayedBets, ...displayedComments, ...(displayedNewContracts ?? [])], + (i) => i.createdTime + ) + .reverse() + .filter((i) => + // filter out comments and bets on ignored/off-topic contracts + 'contractId' in i ? contractsById[i.contractId] : true + ) + + const startIndex = + range(0, items.length - count).find((i) => + items + .slice(i, i + count) + .every((item) => + 'contractId' in item ? contractsById[item.contractId] : true + ) + ) ?? 0 + const itemsSubset = items.slice(startIndex, startIndex + count) + const allLoaded = + realtimeBets && + realtimeComments && + contracts && + activeContracts && + itemsSubset.every((item) => + 'contractId' in item ? contractsById[item.contractId] : true + ) + + const groups = orderBy( + Object.entries( + groupBy(itemsSubset, (item) => + 'contractId' in item ? item.contractId : item.id + ) + ).map(([parentId, items]) => ({ + parentId, + items, + })), + ({ items }) => + // get the largest createdTime of any item in the group + Math.max(...items.map((item) => item.createdTime)), + 'desc' + ) + + return ( + + {!allLoaded && } + {allLoaded && ( + + {groups.map(({ parentId, items }) => { + const contract = contractsById[parentId] as Contract + + return ( + + + {items.map((item) => + 'amount' in item ? ( + + ) : 'question' in item ? ( + + ) : 'channelId' in item ? null : ( + + ) + )} + + ) + })} + + )} + + ) +} + +const MarketCreatedLog = memo((props: { contract: Contract }) => { + const { + creatorId, + creatorAvatarUrl, + creatorUsername, + creatorName, + createdTime, + } = props.contract + + return ( + + + + + + created + + + + + ) +}) + +const CommentLog = memo(function FeedComment(props: { + comment: ContractComment +}) { + const { comment } = props + const { + userName, + text, + content, + userId, + userUsername, + userAvatarUrl, + createdTime, + } = comment + + return ( + + + + + + + + + {' '} + commented + + + + + + ) +}) diff --git a/web/pages/activity.tsx b/web/pages/activity.tsx new file mode 100644 index 0000000000..bcd4b346ed --- /dev/null +++ b/web/pages/activity.tsx @@ -0,0 +1,31 @@ +import { Col } from 'web/components/layout/col' +import { Page } from 'web/components/layout/page' +import { SEO } from 'web/components/SEO' +import { Row } from 'web/components/layout/row' +import { SiteActivity } from 'web/components/site-activity' +import { TRADE_TERM } from 'common/envs/constants' + +export default function ActivityPage() { + return ( + + + + + + + Activity + + + + + + ) +} From 16144b0b128f31bd4c56a671492c09b8e9ea7071 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 14:57:20 -0800 Subject: [PATCH 02/14] get-site-activity --- backend/api/src/get-site-activity.ts | 69 ++++++++++ backend/api/src/routes.ts | 2 + common/src/api/schema.ts | 16 +++ web/components/site-activity.tsx | 198 +++++++-------------------- 4 files changed, 136 insertions(+), 149 deletions(-) create mode 100644 backend/api/src/get-site-activity.ts diff --git a/backend/api/src/get-site-activity.ts b/backend/api/src/get-site-activity.ts new file mode 100644 index 0000000000..40116b0d0f --- /dev/null +++ b/backend/api/src/get-site-activity.ts @@ -0,0 +1,69 @@ +import { APIHandler } from 'api/helpers/endpoint' +import { createSupabaseDirectClient } from 'shared/supabase/init' +import { convertContract } from 'common/supabase/contracts' +import { filterDefined } from 'common/util/array' +import { uniqBy } from 'lodash' +import { log } from 'shared/utils' +import { convertBet } from 'common/supabase/bets' +import { convertContractComment } from 'common/supabase/comments' + +export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => { + const { limit, blockedUserIds = [], blockedGroupSlugs = [], blockedContractIds = [] } = props + const pg = createSupabaseDirectClient() + log('getSiteActivity called', { limit }) + + const [recentBets, recentComments, newContracts] = await Promise.all([ + pg.manyOrNone( + `select * from contract_bets + where amount >= 500 + and user_id != all($1) + and contract_id != all($2) + order by created_time desc limit $3`, + [blockedUserIds, blockedContractIds, limit * 3] + ), + pg.manyOrNone( + `select * from contract_comments + where (likes - coalesce(dislikes, 0)) >= 2 + and user_id != all($1) + and contract_id != all($2) + order by created_time desc limit $3`, + [blockedUserIds, blockedContractIds, limit * 3] + ), + pg.manyOrNone( + `select * from contracts + where visibility = 'public' + and tier != 'play' + and creator_id != all($1) + and id != all($2) + and not exists ( + select 1 from group_contracts gc + join groups g on g.id = gc.group_id + where gc.contract_id = contracts.id + and g.slug = any($3) + ) + order by created_time desc limit $4`, + [blockedUserIds, blockedContractIds, blockedGroupSlugs, limit * 3] + ), + ]) + + const contractIds = uniqBy([ + ...recentBets.map((b) => b.contract_id), + ...recentComments.map((c) => c.contract_id) + ], id => id) + + const relatedContracts = await pg.manyOrNone( + `select * from contracts where id = any($1)`, + [contractIds] + ) + + const contracts = filterDefined([ + ...newContracts.map(convertContract), + ...relatedContracts.map(convertContract) + ]) + + return { + bets: recentBets.map(convertBet), + comments: recentComments.map(convertContractComment), + contracts, + } +} diff --git a/backend/api/src/routes.ts b/backend/api/src/routes.ts index bf5b08e244..5645337b60 100644 --- a/backend/api/src/routes.ts +++ b/backend/api/src/routes.ts @@ -139,6 +139,7 @@ import { generateAIAnswers } from './generate-ai-answers' import { getmonthlybets2024 } from './get-monthly-bets-2024' import { getmaxminprofit2024 } from './get-max-min-profit-2024' import { getNextLoanAmount } from './get-next-loan-amount' +import { getSiteActivity } from './get-site-activity' // we define the handlers in this object in order to typecheck that every API has a handler export const handlers: { [k in APIPath]: APIHandler } = { @@ -297,4 +298,5 @@ export const handlers: { [k in APIPath]: APIHandler } = { 'get-monthly-bets-2024': getmonthlybets2024, 'get-max-min-profit-2024': getmaxminprofit2024, 'get-next-loan-amount': getNextLoanAmount, + 'get-site-activity': getSiteActivity, } diff --git a/common/src/api/schema.ts b/common/src/api/schema.ts index 7a59cbb602..7fd7f45203 100644 --- a/common/src/api/schema.ts +++ b/common/src/api/schema.ts @@ -1913,6 +1913,22 @@ export const API = (_apiTypeCheck = { userId: z.string(), }), }, + 'get-site-activity': { + method: 'GET', + visibility: 'public', + authed: false, + returns: {} as { + bets: Bet[] + comments: ContractComment[] + contracts: Contract[] + }, + props: z.object({ + limit: z.number().default(50), + blockedUserIds: z.array(z.string()).optional(), + blockedGroupSlugs: z.array(z.string()).optional(), + blockedContractIds: z.array(z.string()).optional(), + }).strict(), + }, } as const) export type APIPath = keyof typeof API diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index 21b68ba827..67f9b9249e 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -1,27 +1,8 @@ import clsx from 'clsx' import { ContractComment } from 'common/comment' import { Contract } from 'common/contract' -import { filterDefined } from 'common/util/array' -import { - groupBy, - keyBy, - orderBy, - partition, - range, - sortBy, - uniq, - uniqBy, -} from 'lodash' +import { groupBy, keyBy, orderBy } from 'lodash' import { memo } from 'react' -import { useBetsOnce, useSubscribeGlobalBets } from 'web/hooks/use-bets' -import { - useGlobalComments, - useSubscribeGlobalComments, -} from 'web/hooks/use-comments' -import { - usePublicContracts, - useLiveAllNewContracts, -} from 'web/hooks/use-contract' import { usePrivateUser } from 'web/hooks/use-user' import { ContractMention } from './contract/contract-mention' import { FeedBet } from './feed/feed-bets' @@ -33,27 +14,14 @@ import { Content } from './widgets/editor' import { LoadingIndicator } from './widgets/loading-indicator' import { UserLink } from './widgets/user-link' import { UserHovercard } from './user/user-hovercard' +import { useAPIGetter } from 'web/hooks/use-api-getter' import { Bet } from 'common/bet' -const filterBets = (bet: Bet, contract: Contract | undefined) => - bet.amount >= 500 || (contract?.token === 'CASH' && bet.amount >= 5) - -const filterComments = ( - comment: ContractComment, - contract: Contract | undefined -) => (comment.likes ?? 0) - (comment.dislikes ?? 0) >= 2 - -const filterNewContracts = (contract: Contract) => - contract.marketTier !== 'play' - -const count = 50 - export function SiteActivity(props: { className?: string blockedUserIds?: string[] }) { const { className } = props - const privateUser = usePrivateUser() const blockedGroupSlugs = privateUser?.blockedGroupSlugs ?? [] @@ -62,104 +30,38 @@ export function SiteActivity(props: { props.blockedUserIds ?? [] ) - const recentBets = useBetsOnce({ - limit: count * 3, - filterRedemptions: true, - order: 'desc', + const { data, loading } = useAPIGetter('get-site-activity', { + // limit: 50, + // blockedUserIds, + // blockedGroupSlugs, + // blockedContractIds, }) - const allRealtimeBets = useSubscribeGlobalBets({ - filterRedemptions: true, - }) - const realtimeBets = sortBy(allRealtimeBets, 'createdTime') - .reverse() - .slice(0, count * 3) - - const recentComments = useGlobalComments(count * 3) - const realtimeComments = useSubscribeGlobalComments() - const newContracts = useLiveAllNewContracts(count * 3)?.filter( - (c) => - !blockedContractIds.includes(c.id) && - !blockedUserIds.includes(c.creatorId) && - c.visibility === 'public' && - (!c.groupSlugs?.some((slug) => blockedGroupSlugs.includes(slug)) || true) - ) - const bets = uniqBy( - [...(realtimeBets ?? []), ...(recentBets ?? [])], - 'id' - ).filter( - (bet) => - !blockedContractIds.includes(bet.contractId) && - !blockedUserIds.includes(bet.userId) - ) - const comments = uniqBy( - [...(realtimeComments ?? []), ...(recentComments ?? [])], - 'id' - ).filter( - (c) => - c.commentType === 'contract' && - !blockedContractIds.includes(c.contractId) && - !blockedUserIds.includes(c.userId) - ) + if (loading || !data) return - const activeContractIds = uniq([ - ...bets.map((b) => b.contractId), - ...comments.map((c) => c.contractId), - ]) + const { bets, comments, contracts } = data + console.log('contracts', contracts.find((c) => typeof c === 'string')) + console.log('comments', comments.find((c) => typeof c === 'string')) + console.log('bets', bets.find((c) => typeof c === 'string')) - const activeContracts = usePublicContracts( - activeContractIds, - undefined, - blockedGroupSlugs - ) - - const [contracts, _unlistedContracts] = partition( - filterDefined(activeContracts ?? []).concat(newContracts ?? []), - (c) => c.visibility === 'public' - ) const contractsById = keyBy(contracts, 'id') - const displayedBets = bets.filter((bet) => - filterBets(bet, contractsById[bet.contractId]) - ) - - const displayedComments = comments.filter((comment) => - filterComments(comment, contractsById[comment.contractId]) + const items = orderBy( + [...bets, ...comments, ...contracts], + 'createdTime', + 'desc' ) - const displayedNewContracts = newContracts?.filter(filterNewContracts) + console.log('first bet', bets[0]) + console.log('first comment', comments[0]) + console.log('first contract', contracts[0]) - const items = sortBy( - [...displayedBets, ...displayedComments, ...(displayedNewContracts ?? [])], - (i) => i.createdTime - ) - .reverse() - .filter((i) => - // filter out comments and bets on ignored/off-topic contracts - 'contractId' in i ? contractsById[i.contractId] : true - ) + console.log('items', items) - const startIndex = - range(0, items.length - count).find((i) => - items - .slice(i, i + count) - .every((item) => - 'contractId' in item ? contractsById[item.contractId] : true - ) - ) ?? 0 - const itemsSubset = items.slice(startIndex, startIndex + count) - const allLoaded = - realtimeBets && - realtimeComments && - contracts && - activeContracts && - itemsSubset.every((item) => - 'contractId' in item ? contractsById[item.contractId] : true - ) const groups = orderBy( Object.entries( - groupBy(itemsSubset, (item) => + groupBy(items, (item) => 'contractId' in item ? item.contractId : item.id ) ).map(([parentId, items]) => ({ @@ -167,42 +69,40 @@ export function SiteActivity(props: { items, })), ({ items }) => - // get the largest createdTime of any item in the group Math.max(...items.map((item) => item.createdTime)), 'desc' ) + console.log('groups', groups) + return ( - {!allLoaded && } - {allLoaded && ( - - {groups.map(({ parentId, items }) => { - const contract = contractsById[parentId] as Contract - - return ( - - - {items.map((item) => - 'amount' in item ? ( - - ) : 'question' in item ? ( - - ) : 'channelId' in item ? null : ( - - ) - )} - - ) - })} - - )} + + {groups.map(({ parentId, items }) => { + const contract = contractsById[parentId] as Contract + + return ( + + + {items.map((item) => + 'amount' in item ? ( + + ) : 'question' in item ? ( + + ) : 'channelId' in item ? null : ( + + ) + )} + + ) + })} + ) } From 93c14f36ccfedcdd124b0560b83e4a2bf91a1c91 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 15:08:44 -0800 Subject: [PATCH 03/14] fix contracts issue --- backend/api/src/get-site-activity.ts | 8 ++------ common/src/api/schema.ts | 5 +++-- web/components/site-activity.tsx | 11 ++++------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/backend/api/src/get-site-activity.ts b/backend/api/src/get-site-activity.ts index 40116b0d0f..d119887950 100644 --- a/backend/api/src/get-site-activity.ts +++ b/backend/api/src/get-site-activity.ts @@ -56,14 +56,10 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => [contractIds] ) - const contracts = filterDefined([ - ...newContracts.map(convertContract), - ...relatedContracts.map(convertContract) - ]) - return { bets: recentBets.map(convertBet), comments: recentComments.map(convertContractComment), - contracts, + newContracts: filterDefined(newContracts.map(convertContract)), + relatedContracts: filterDefined(relatedContracts.map(convertContract)) } } diff --git a/common/src/api/schema.ts b/common/src/api/schema.ts index 7fd7f45203..3e922e58ae 100644 --- a/common/src/api/schema.ts +++ b/common/src/api/schema.ts @@ -1920,10 +1920,11 @@ export const API = (_apiTypeCheck = { returns: {} as { bets: Bet[] comments: ContractComment[] - contracts: Contract[] + newContracts: Contract[] + relatedContracts: Contract[] }, props: z.object({ - limit: z.number().default(50), + limit: z.coerce.number().default(10), blockedUserIds: z.array(z.string()).optional(), blockedGroupSlugs: z.array(z.string()).optional(), blockedContractIds: z.array(z.string()).optional(), diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index 67f9b9249e..26e2353e46 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -31,7 +31,7 @@ export function SiteActivity(props: { ) const { data, loading } = useAPIGetter('get-site-activity', { - // limit: 50, + limit: 10, // blockedUserIds, // blockedGroupSlugs, // blockedContractIds, @@ -39,15 +39,12 @@ export function SiteActivity(props: { if (loading || !data) return - const { bets, comments, contracts } = data - console.log('contracts', contracts.find((c) => typeof c === 'string')) - console.log('comments', comments.find((c) => typeof c === 'string')) - console.log('bets', bets.find((c) => typeof c === 'string')) - + const { bets, comments, newContracts, relatedContracts } = data + const contracts = [...newContracts, ...relatedContracts] const contractsById = keyBy(contracts, 'id') const items = orderBy( - [...bets, ...comments, ...contracts], + [...bets, ...comments, ...newContracts], 'createdTime', 'desc' ) From 82397970f1280505d280a585d24a5272bc549083 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 15:10:50 -0800 Subject: [PATCH 04/14] pass params --- web/components/site-activity.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index 26e2353e46..c689f7af5d 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -15,7 +15,6 @@ import { LoadingIndicator } from './widgets/loading-indicator' import { UserLink } from './widgets/user-link' import { UserHovercard } from './user/user-hovercard' import { useAPIGetter } from 'web/hooks/use-api-getter' -import { Bet } from 'common/bet' export function SiteActivity(props: { className?: string @@ -32,9 +31,9 @@ export function SiteActivity(props: { const { data, loading } = useAPIGetter('get-site-activity', { limit: 10, - // blockedUserIds, - // blockedGroupSlugs, - // blockedContractIds, + blockedUserIds, + blockedGroupSlugs, + blockedContractIds, }) if (loading || !data) return From 43f2f66fdbe0987ad820ab2d3f19883b167d5278 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 15:14:45 -0800 Subject: [PATCH 05/14] remove comments --- web/components/site-activity.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index c689f7af5d..ea93007a3c 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -48,13 +48,6 @@ export function SiteActivity(props: { 'desc' ) - console.log('first bet', bets[0]) - console.log('first comment', comments[0]) - console.log('first contract', contracts[0]) - - console.log('items', items) - - const groups = orderBy( Object.entries( groupBy(items, (item) => @@ -69,8 +62,6 @@ export function SiteActivity(props: { 'desc' ) - console.log('groups', groups) - return ( From e4692270b2ae3dc2e6c353c8f8e55e041f0198b3 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 16:22:59 -0800 Subject: [PATCH 06/14] adjust limits --- backend/api/src/get-site-activity.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/api/src/get-site-activity.ts b/backend/api/src/get-site-activity.ts index d119887950..d7aa882530 100644 --- a/backend/api/src/get-site-activity.ts +++ b/backend/api/src/get-site-activity.ts @@ -19,7 +19,7 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => and user_id != all($1) and contract_id != all($2) order by created_time desc limit $3`, - [blockedUserIds, blockedContractIds, limit * 3] + [blockedUserIds, blockedContractIds, limit * 5] ), pg.manyOrNone( `select * from contract_comments @@ -27,7 +27,7 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => and user_id != all($1) and contract_id != all($2) order by created_time desc limit $3`, - [blockedUserIds, blockedContractIds, limit * 3] + [blockedUserIds, blockedContractIds, limit] ), pg.manyOrNone( `select * from contracts @@ -42,7 +42,7 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => and g.slug = any($3) ) order by created_time desc limit $4`, - [blockedUserIds, blockedContractIds, blockedGroupSlugs, limit * 3] + [blockedUserIds, blockedContractIds, blockedGroupSlugs, limit] ), ]) From c4bdb72ed97603a3b9cbb202ed93526db1c21a52 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 16:49:55 -0800 Subject: [PATCH 07/14] styling --- web/components/contract/contract-mention.tsx | 20 ++++++---- web/components/feed/feed-bets.tsx | 3 +- web/components/site-activity.tsx | 39 +++++++++++--------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/web/components/contract/contract-mention.tsx b/web/components/contract/contract-mention.tsx index c394d43e76..5c76f0f7d1 100644 --- a/web/components/contract/contract-mention.tsx +++ b/web/components/contract/contract-mention.tsx @@ -28,14 +28,18 @@ export function ContractMention(props: { {contract.question} - - - + + {contract.outcomeType === 'BINARY' && ( + + + + )} + {!contract.resolution && probChange && ( {probChange} )} diff --git a/web/components/feed/feed-bets.tsx b/web/components/feed/feed-bets.tsx index bf7e047819..d6a83497ba 100644 --- a/web/components/feed/feed-bets.tsx +++ b/web/components/feed/feed-bets.tsx @@ -39,7 +39,7 @@ export const FeedBet = memo(function FeedBet(props: { className?: string onReply?: (bet: Bet) => void }) { - const { contract, bet, avatarSize, className, onReply } = props + const { contract, bet, avatarSize, className } = props const { createdTime, userId } = bet const user = useDisplayUserById(userId) const showUser = dayjs(createdTime).isAfter('2022-06-01') @@ -66,7 +66,6 @@ export const FeedBet = memo(function FeedBet(props: { className="flex-1" /> - ) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index ea93007a3c..f255eb7faa 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -64,28 +64,33 @@ export function SiteActivity(props: { return ( - + {groups.map(({ parentId, items }) => { const contract = contractsById[parentId] as Contract return ( - + - {items.map((item) => - 'amount' in item ? ( - - ) : 'question' in item ? ( - - ) : 'channelId' in item ? null : ( - - ) - )} +
+ {items.map((item) => + 'amount' in item ? ( + + ) : 'question' in item ? ( + + ) : 'channelId' in item ? null : ( + + ) + )} +
) })} From f75e8c092d3d835c2b6969667a779cbf4eaa3258 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 17:06:24 -0800 Subject: [PATCH 08/14] feed images --- web/components/site-activity.tsx | 47 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index f255eb7faa..396d93288c 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -71,26 +71,37 @@ export function SiteActivity(props: { return ( - -
- {items.map((item) => - 'amount' in item ? ( - - ) : 'question' in item ? ( - - ) : 'channelId' in item ? null : ( - - ) + + + +
+ {items.map((item) => + 'amount' in item ? ( + + ) : 'question' in item ? ( + + ) : 'channelId' in item ? null : ( + + ) + )} +
+ + {contract.coverImageUrl && ( + )} -
+ ) })} From 8ca82ff59c17ab24140d9c54f25ca64559f38bbf Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 17:14:47 -0800 Subject: [PATCH 09/14] contract mention: don't open in new tab --- web/components/contract/contract-mention.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/components/contract/contract-mention.tsx b/web/components/contract/contract-mention.tsx index 5c76f0f7d1..eb86cfab15 100644 --- a/web/components/contract/contract-mention.tsx +++ b/web/components/contract/contract-mention.tsx @@ -4,7 +4,6 @@ import { TRADED_TERM } from 'common/envs/constants' import { formatWithToken } from 'common/util/format' import Link from 'next/link' import { useIsClient } from 'web/hooks/use-is-client' -import { getIsNative } from 'web/lib/native/is-native' import { fromNow } from 'web/lib/util/time' import { ContractStatusLabel } from './contracts-table' import { getTextColor } from './text-color' @@ -23,7 +22,7 @@ export function ContractMention(props: { href={contractPath(contract)} className={clsx('group inline whitespace-nowrap rounded-sm', className)} title={isClient ? tooltipLabel(contract) : undefined} - target={getIsNative() ? '_self' : '_blank'} + // target={getIsNative() ? '_self' : '_blank'} > {contract.question} From c6d1d39044d519429ba6845f22d1924cdc35f213 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 17:35:11 -0800 Subject: [PATCH 10/14] conditionally show description --- web/components/site-activity.tsx | 77 ++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index 396d93288c..22ec962e32 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -57,8 +57,7 @@ export function SiteActivity(props: { parentId, items, })), - ({ items }) => - Math.max(...items.map((item) => item.createdTime)), + ({ items }) => Math.max(...items.map((item) => item.createdTime)), 'desc' ) @@ -87,7 +86,11 @@ export function SiteActivity(props: { avatarSize="xs" /> ) : 'question' in item ? ( - + ) : 'channelId' in item ? null : ( ) @@ -110,34 +113,50 @@ export function SiteActivity(props: { ) } -const MarketCreatedLog = memo((props: { contract: Contract }) => { - const { - creatorId, - creatorAvatarUrl, - creatorUsername, - creatorName, - createdTime, - } = props.contract +const MarketCreatedLog = memo( + (props: { contract: Contract; showDescription?: boolean }) => { + const { + creatorId, + creatorAvatarUrl, + creatorUsername, + creatorName, + createdTime, + } = props.contract + const { showDescription = false } = props - return ( - - - - - - created - + return ( + + + + + + created + + - - - ) -}) + + {showDescription && props.contract.description && ( + // TODO: truncate if too long + + )} + + ) + } +) const CommentLog = memo(function FeedComment(props: { comment: ContractComment From 10882aca0f431b37c6058f56e7787f5d4863ec49 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 18:14:40 -0800 Subject: [PATCH 11/14] move description outside hovercard --- web/components/site-activity.tsx | 40 +++++++++++++++++--------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index 22ec962e32..9ef7da0fb3 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -125,25 +125,27 @@ const MarketCreatedLog = memo( const { showDescription = false } = props return ( - - - - - - created - + + + + + + + created + + - + {showDescription && props.contract.description && ( // TODO: truncate if too long @@ -153,7 +155,7 @@ const MarketCreatedLog = memo( className="mt-2 text-left" /> )} - + ) } ) From 7b5fff759d25cf0794ed06ad83ee35be0c841a79 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 19:21:42 -0800 Subject: [PATCH 12/14] todos --- backend/api/src/get-site-activity.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/api/src/get-site-activity.ts b/backend/api/src/get-site-activity.ts index d7aa882530..da8a5cd65a 100644 --- a/backend/api/src/get-site-activity.ts +++ b/backend/api/src/get-site-activity.ts @@ -13,6 +13,10 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => log('getSiteActivity called', { limit }) const [recentBets, recentComments, newContracts] = await Promise.all([ + // todo: show + // [ ] sweepcash bets >= 5 + // [ ] large limit orders + // [ ] personalization based on followed users & topics pg.manyOrNone( `select * from contract_bets where amount >= 500 From 22d98132dedfaf94f8c16fc206d51639058d1ec0 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 19:29:58 -0800 Subject: [PATCH 13/14] include sales --- backend/api/src/get-site-activity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/api/src/get-site-activity.ts b/backend/api/src/get-site-activity.ts index da8a5cd65a..0ae1aed883 100644 --- a/backend/api/src/get-site-activity.ts +++ b/backend/api/src/get-site-activity.ts @@ -19,7 +19,7 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (props) => // [ ] personalization based on followed users & topics pg.manyOrNone( `select * from contract_bets - where amount >= 500 + where abs(amount) >= 500 and user_id != all($1) and contract_id != all($2) order by created_time desc limit $3`, From 0518c53061c31540343cee56a886dad9f1548987 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 11 Dec 2024 19:40:57 -0800 Subject: [PATCH 14/14] more todos --- web/components/site-activity.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/components/site-activity.tsx b/web/components/site-activity.tsx index 9ef7da0fb3..9ca8681b4b 100644 --- a/web/components/site-activity.tsx +++ b/web/components/site-activity.tsx @@ -159,7 +159,7 @@ const MarketCreatedLog = memo( ) } ) - +// todo: add liking/disliking const CommentLog = memo(function FeedComment(props: { comment: ContractComment }) {