Merge branch 'main' into tourney-launch

This commit is contained in:
Austin Chen 2022-08-26 10:32:29 -07:00
commit 383c417132
13 changed files with 108 additions and 86 deletions

View File

@ -8,11 +8,11 @@
},
"sideEffects": false,
"dependencies": {
"@tiptap/core": "2.0.0-beta.181",
"@tiptap/core": "2.0.0-beta.182",
"@tiptap/extension-image": "2.0.0-beta.30",
"@tiptap/extension-link": "2.0.0-beta.43",
"@tiptap/extension-mention": "2.0.0-beta.102",
"@tiptap/starter-kit": "2.0.0-beta.190",
"@tiptap/starter-kit": "2.0.0-beta.191",
"lodash": "4.17.21"
},
"devDependencies": {

View File

@ -26,11 +26,11 @@
"dependencies": {
"@amplitude/node": "1.10.0",
"@google-cloud/functions-framework": "3.1.2",
"@tiptap/core": "2.0.0-beta.181",
"@tiptap/core": "2.0.0-beta.182",
"@tiptap/extension-image": "2.0.0-beta.30",
"@tiptap/extension-link": "2.0.0-beta.43",
"@tiptap/extension-mention": "2.0.0-beta.102",
"@tiptap/starter-kit": "2.0.0-beta.190",
"@tiptap/starter-kit": "2.0.0-beta.191",
"cors": "2.8.5",
"dayjs": "1.11.4",
"express": "4.18.1",

View File

@ -71,10 +71,11 @@ export const AnswersGraph = memo(function AnswersGraph(props: {
const yTickValues = [0, 25, 50, 75, 100]
const numXTickValues = isLargeWidth ? 5 : 2
const hoursAgo = latestTime.subtract(5, 'hours')
const startDate = dayjs(contract.createdTime).isBefore(hoursAgo)
? new Date(contract.createdTime)
: hoursAgo.toDate()
const startDate = new Date(contract.createdTime)
const endDate = dayjs(startDate).add(1, 'hour').isAfter(latestTime)
? latestTime.add(1, 'hours').toDate()
: latestTime.toDate()
const includeMinute = dayjs(endDate).diff(startDate, 'hours') < 2
const multiYear = !dayjs(startDate).isSame(latestTime, 'year')
const lessThanAWeek = dayjs(startDate).add(1, 'week').isAfter(latestTime)
@ -96,16 +97,24 @@ export const AnswersGraph = memo(function AnswersGraph(props: {
xScale={{
type: 'time',
min: startDate,
max: latestTime.toDate(),
max: endDate,
}}
xFormat={(d) =>
formatTime(+d.valueOf(), multiYear, lessThanAWeek, lessThanAWeek)
}
axisBottom={{
tickValues: numXTickValues,
format: (time) => formatTime(+time, multiYear, lessThanAWeek, false),
format: (time) =>
formatTime(+time, multiYear, lessThanAWeek, includeMinute),
}}
colors={{ scheme: 'pastel1' }}
colors={[
'#fca5a5', // red-300
'#93c5fd', // blue-300
'#86efac', // green-300
'#f9a8d4', // pink-300
'#a5b4fc', // indigo-300
'#fcd34d', // amber-300
]}
pointSize={0}
curve="stepAfter"
enableSlices="x"
@ -156,7 +165,11 @@ function formatTime(
) {
const d = dayjs(time)
if (d.add(1, 'minute').isAfter(Date.now())) return 'Now'
if (
d.add(1, 'minute').isAfter(Date.now()) &&
d.subtract(1, 'minute').isBefore(Date.now())
)
return 'Now'
let format: string
if (d.isSame(Date.now(), 'day')) {

View File

@ -1,9 +0,0 @@
import { SparklesIcon } from '@heroicons/react/solid'
export function FeaturedContractBadge() {
return (
<span className="inline-flex items-center gap-1 rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-blue-800">
<SparklesIcon className="h-4 w-4" aria-hidden="true" /> Featured
</span>
)
}

View File

@ -5,12 +5,15 @@ import {
TrendingUpIcon,
UserGroupIcon,
} from '@heroicons/react/outline'
import Router from 'next/router'
import clsx from 'clsx'
import { Editor } from '@tiptap/react'
import dayjs from 'dayjs'
import { Row } from '../layout/row'
import { formatMoney } from 'common/util/format'
import { UserLink } from '../user-page'
import { Contract, updateContract } from 'web/lib/firebase/contracts'
import dayjs from 'dayjs'
import { DateTimeTooltip } from '../datetime-tooltip'
import { fromNow } from 'web/lib/util/time'
import { Avatar } from '../avatar'
@ -21,7 +24,6 @@ import NewContractBadge from '../new-contract-badge'
import { UserFollowButton } from '../follow-button'
import { DAY_MS } from 'common/util/time'
import { useUser } from 'web/hooks/use-user'
import { Editor } from '@tiptap/react'
import { exhibitExts } from 'common/util/parse'
import { Button } from 'web/components/button'
import { Modal } from 'web/components/layout/modal'
@ -30,10 +32,9 @@ import { ContractGroupsList } from 'web/components/groups/contract-groups-list'
import { SiteLink } from 'web/components/site-link'
import { groupPath } from 'web/lib/firebase/groups'
import { insertContent } from '../editor/utils'
import clsx from 'clsx'
import { contractMetrics } from 'common/contract-details'
import { User } from 'common/user'
import { FeaturedContractBadge } from 'web/components/contract/FeaturedContractBadge'
import { FeaturedContractBadge } from 'web/components/contract/featured-contract-badge'
export type ShowTime = 'resolve-date' | 'close-date'
@ -191,7 +192,11 @@ export function ContractDetails(props: {
size={'xs'}
className={'max-w-[200px]'}
color={'gray-white'}
onClick={() => setOpen(!open)}
onClick={() =>
groupToDisplay
? Router.push(groupPath(groupToDisplay.slug))
: setOpen(!open)
}
>
{groupInfo}
</Button>

View File

@ -17,6 +17,7 @@ import { useAdmin, useDev } from 'web/hooks/use-admin'
import { SiteLink } from '../site-link'
import { firestoreConsolePath } from 'common/envs/constants'
import { deleteField } from 'firebase/firestore'
import ShortToggle from '../widgets/short-toggle'
export const contractDetailsButtonClassName =
'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500'
@ -50,6 +51,21 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
? 'Multiple choice'
: 'Numeric'
const onFeaturedToggle = async (enabled: boolean) => {
if (
enabled &&
(contract.featuredOnHomeRank === 0 || !contract?.featuredOnHomeRank)
) {
await updateContract(id, { featuredOnHomeRank: 1 })
setFeatured(true)
} else if (!enabled && (contract?.featuredOnHomeRank ?? 0) > 0) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
await updateContract(id, { featuredOnHomeRank: deleteField() })
setFeatured(false)
}
}
return (
<>
<button
@ -144,43 +160,13 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
)}
{isAdmin && (
<tr>
<td>Set featured</td>
<td>[ADMIN] Featured</td>
<td>
<select
className="select select-bordered"
value={featured ? 'true' : 'false'}
onChange={(e) => {
const newVal = e.target.value === 'true'
if (
newVal &&
(contract.featuredOnHomeRank === 0 ||
!contract?.featuredOnHomeRank)
)
updateContract(id, {
featuredOnHomeRank: 1,
})
.then(() => {
setFeatured(true)
})
.catch(console.error)
else if (
!newVal &&
(contract?.featuredOnHomeRank ?? 0) > 0
)
updateContract(id, {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
featuredOnHomeRank: deleteField(),
})
.then(() => {
setFeatured(false)
})
.catch(console.error)
}}
>
<option value="false">false</option>
<option value="true">true</option>
</select>
<ShortToggle
enabled={featured}
setEnabled={setFeatured}
onChange={onFeaturedToggle}
/>
</td>
</tr>
)}

View File

@ -58,10 +58,11 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
const { width } = useWindowSize()
const numXTickValues = !width || width < 800 ? 2 : 5
const hoursAgo = latestTime.subtract(1, 'hours')
const startDate = dayjs(times[0]).isBefore(hoursAgo)
? times[0]
: hoursAgo.toDate()
const startDate = times[0]
const endDate = dayjs(startDate).add(1, 'hour').isAfter(latestTime)
? latestTime.add(1, 'hours').toDate()
: latestTime.toDate()
const includeMinute = dayjs(endDate).diff(startDate, 'hours') < 2
// Minimum number of points for the graph to have. For smooth tooltip movement
// On first load, width is undefined, skip adding extra points to let page load faster
@ -133,14 +134,15 @@ export const ContractProbGraph = memo(function ContractProbGraph(props: {
xScale={{
type: 'time',
min: startDate,
max: latestTime.toDate(),
max: endDate,
}}
xFormat={(d) =>
formatTime(+d.valueOf(), multiYear, lessThanAWeek, lessThanAWeek)
}
axisBottom={{
tickValues: numXTickValues,
format: (time) => formatTime(+time, multiYear, lessThanAWeek, false),
format: (time) =>
formatTime(+time, multiYear, lessThanAWeek, includeMinute),
}}
colors={{ datum: 'color' }}
curve="stepAfter"
@ -183,7 +185,11 @@ function formatTime(
) {
const d = dayjs(time)
if (d.add(1, 'minute').isAfter(Date.now())) return 'Now'
if (
d.add(1, 'minute').isAfter(Date.now()) &&
d.subtract(1, 'minute').isBefore(Date.now())
)
return 'Now'
let format: string
if (d.isSame(Date.now(), 'day')) {

View File

@ -0,0 +1,9 @@
import { BadgeCheckIcon } from '@heroicons/react/solid'
export function FeaturedContractBadge() {
return (
<span className="inline-flex items-center gap-1 rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800">
<BadgeCheckIcon className="h-4 w-4" aria-hidden="true" /> Featured
</span>
)
}

View File

@ -5,13 +5,19 @@ import clsx from 'clsx'
export default function ShortToggle(props: {
enabled: boolean
setEnabled: (enabled: boolean) => void
onChange?: (enabled: boolean) => void
}) {
const { enabled, setEnabled } = props
return (
<Switch
checked={enabled}
onChange={setEnabled}
onChange={(e: boolean) => {
setEnabled(e)
if (props.onChange) {
props.onChange(e)
}
}}
className="group relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span className="sr-only">Use setting</span>

View File

@ -27,14 +27,14 @@
"@nivo/line": "0.74.0",
"@nivo/tooltip": "0.74.0",
"@react-query-firebase/firestore": "0.4.2",
"@tiptap/core": "2.0.0-beta.181",
"@tiptap/core": "2.0.0-beta.182",
"@tiptap/extension-character-count": "2.0.0-beta.31",
"@tiptap/extension-image": "2.0.0-beta.30",
"@tiptap/extension-link": "2.0.0-beta.43",
"@tiptap/extension-mention": "2.0.0-beta.102",
"@tiptap/extension-placeholder": "2.0.0-beta.53",
"@tiptap/react": "2.0.0-beta.114",
"@tiptap/starter-kit": "2.0.0-beta.190",
"@tiptap/starter-kit": "2.0.0-beta.191",
"algoliasearch": "4.13.0",
"browser-image-compression": "2.0.0",
"clsx": "1.1.1",

View File

@ -166,7 +166,8 @@ export function ContractEmbed(props: { contract: Contract; bets: Bet[] }) {
/>
)}
{outcomeType === 'FREE_RESPONSE' && (
{(outcomeType === 'FREE_RESPONSE' ||
outcomeType === 'MULTIPLE_CHOICE') && (
<AnswersGraph contract={contract} bets={bets} height={graphHeight} />
)}

View File

@ -200,7 +200,9 @@ function IncomeNotificationGroupItem(props: {
const { notificationGroup, className } = props
const { notifications } = notificationGroup
const numSummaryLines = 3
const [expanded, setExpanded] = useState(false)
const [expanded, setExpanded] = useState(
notifications.length <= numSummaryLines
)
const [highlighted, setHighlighted] = useState(
notifications.some((n) => !n.isSeen)
)
@ -398,7 +400,8 @@ function IncomeNotificationItem(props: {
} else if (sourceType === 'tip') {
reasonText = !simple ? `tipped you on` : `in tips on`
} else if (sourceType === 'betting_streak_bonus') {
reasonText = 'for your'
if (sourceText && +sourceText === 50) reasonText = '(max) for your'
else reasonText = 'for your'
} else if (sourceType === 'loan' && sourceText) {
reasonText = `of your invested bets returned as a`
}
@ -524,7 +527,7 @@ function IncomeNotificationItem(props: {
</span>
</div>
</Row>
<div className={'mt-4 border-b border-gray-300'} />
<div className={'border-b border-gray-300 pt-4'} />
</div>
</div>
)
@ -541,7 +544,9 @@ function NotificationGroupItem(props: {
const isMobile = (width && width < 768) || false
const numSummaryLines = 3
const [expanded, setExpanded] = useState(false)
const [expanded, setExpanded] = useState(
notifications.length <= numSummaryLines
)
const [highlighted, setHighlighted] = useState(
notifications.some((n) => !n.isSeen)
)

View File

@ -2919,10 +2919,10 @@
lodash.isplainobject "^4.0.6"
lodash.merge "^4.6.2"
"@tiptap/core@2.0.0-beta.181", "@tiptap/core@^2.0.0-beta.181":
version "2.0.0-beta.181"
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.181.tgz#07aeea26336814ab82eb7f4199b17538187c6fbb"
integrity sha512-tbwRqjTVvY9v31TNAH6W0Njhr/OVwI28zWXmH55/USrwyU2CB1iCVfXktZKOhB+8WyvOaBv1JA5YplMIhstYTw==
"@tiptap/core@2.0.0-beta.182", "@tiptap/core@^2.0.0-beta.182":
version "2.0.0-beta.182"
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.182.tgz#d2001e9b765adda95e15d171479860a3349e2d04"
integrity sha512-MZGkMGnVnWhBzjvpBNwQ9zBz38ndi3Irbf90uCTSArR0kaCVkW4vmyuPuOXd+0SO8Yv/l5oyDdOCpaG3rnQYfw==
dependencies:
prosemirror-commands "1.3.0"
prosemirror-keymap "1.2.0"
@ -3099,12 +3099,12 @@
"@tiptap/extension-floating-menu" "^2.0.0-beta.56"
prosemirror-view "1.26.2"
"@tiptap/starter-kit@2.0.0-beta.190":
version "2.0.0-beta.190"
resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.190.tgz#fe0021e29d070fc5707722513a398c8884e15f71"
integrity sha512-jaFMkE6mjCHmCJsXUyLiXGYRVDcHF+PbH/5hEu1riUIAT0Hmm7uak5TYsPeuoCVN7P/tmDEBbBRASZ5CzEQpvw==
"@tiptap/starter-kit@2.0.0-beta.191":
version "2.0.0-beta.191"
resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.191.tgz#3f549367f6dbb8cf83f63aa0941722d91d0fd8e7"
integrity sha512-YRrBCi9W4jiH/xLTJJOCdD7pL4Wb98Ip8qCJ94RElShDj0O1i5tT9wWlgVWoGIU+CRAds5XENRwZ97sJ+YfYyg==
dependencies:
"@tiptap/core" "^2.0.0-beta.181"
"@tiptap/core" "^2.0.0-beta.182"
"@tiptap/extension-blockquote" "^2.0.0-beta.29"
"@tiptap/extension-bold" "^2.0.0-beta.28"
"@tiptap/extension-bullet-list" "^2.0.0-beta.29"