manifold/web/components/contract/contract-info-dialog.tsx

217 lines
6.7 KiB
TypeScript
Raw Normal View History

import { DotsHorizontalIcon } from '@heroicons/react/outline'
import clsx from 'clsx'
2022-04-09 23:04:13 +00:00
import dayjs from 'dayjs'
import { useState } from 'react'
2022-09-16 04:08:31 +00:00
import { capitalize } from 'lodash'
2022-04-09 23:04:13 +00:00
import { Contract } from 'common/contract'
import { formatMoney } from 'common/util/format'
2022-08-25 13:05:26 +00:00
import { contractPool, updateContract } from 'web/lib/firebase/contracts'
import { LiquidityBountyPanel } from 'web/components/contract/liquidity-bounty-panel'
import { Col } from '../layout/col'
import { Modal } from '../layout/modal'
import { Title } from '../title'
import { InfoTooltip } from '../info-tooltip'
import { useAdmin, useDev } from 'web/hooks/use-admin'
import { SiteLink } from '../site-link'
import { firestoreConsolePath } from 'common/envs/constants'
2022-08-25 13:05:26 +00:00
import { deleteField } from 'firebase/firestore'
2022-08-26 02:42:40 +00:00
import ShortToggle from '../widgets/short-toggle'
2022-10-05 14:38:19 +00:00
import { DuplicateContractButton } from '../duplicate-contract-button'
import { Row } from '../layout/row'
2022-10-03 15:26:39 +00:00
import { BETTORS, User } from 'common/user'
import { Button } from '../button'
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'
export function ContractInfoDialog(props: {
contract: Contract
2022-10-03 15:26:39 +00:00
user: User | null | undefined
className?: string
}) {
2022-10-03 15:26:39 +00:00
const { contract, className, user } = props
Automated market resolution (#404) * Added radio buttons to market creation (non functional) * Ignoring vs code files Should this be done in the repo or should everyone using VS Code do that himself globally on his machine(s)? * Removed 'automatic' resolution * added union type for resolution * revert: resolution could be anything here (non binary markets) * Expanded ChoicesToggleGroup for string choices * Added combined resolution and required buttons to market creation * restricted automatic resolution to binary markets * added automatic resolution to contract * added automatic resolution to contract overview * string or number array to mixed array * created const for resolutions * Added comments for leading semicolons * configuration of auto resolution on market creation * v1.22.19 * v1.0.0 * v0.0.0 * v1.0.0 * v1.22.19 * Mock display automatic resolution * Revert changes to market creation * Revert "v1.22.19" This reverts commit 22f59adc9cd15eb5dc3a30c362b7d90eb3f5f230. * Removed resolutiontype from contract creation * Added auto resolution time to contract * Auto resolution date editable * refactoring * Editable interface for auto resolution * New edit interface for auto resolution * Setting of auto resolve date when changing close date * prohibited changing other peoples markets * removed unnecessary export * refactoring (cherry picked from commit 4de86d5b08f9bc1d960b51746260a5b8c5d9b1fd) * Added comments for leading semicolons (cherry picked from commit 60739c7853ce611a12227887f1a115f75e957d8e) * Ignoring vs code files Should this be done in the repo or should everyone using VS Code do that himself globally on his machine(s)? (cherry picked from commit 944de9398a03ff9e5b2fccefa69935b4d9fa4b32) * removed unused imports and variables * added type for binary resolution * Prettier * const for binary resolutions * using the type "resolution" * Prettier * Re-added comment * Update functions/src/create-contract.ts * Revert "Ignoring vs code files" This reverts commit 09aea5c207bcdc5ee2edb5db70223b5516abe415. * launch config for debugging with vs code WIP * "Launch Chrome" does not work since login via google is not possible in debugger-chrome * Breakpoints are unbound when attached to chrome * Revert "Added comments for leading semicolons" * prettier * linebreak crlf * vscode settings * correct linebreaks * search exclusion * automatic prettifier * vscode settings * correct linebreaks * search exclusion * automatic prettifier * Working debugger config * fix merge * Removed comments, default resolution MKT * removed vscode from gitignore * refactoring description update * Added auto resolution to LiteMarket * fix date, setDate mutates object * fixed firestore.rules * script to add auto resolution to all markets * regularely auto resolve markets * fix description error * moved calculate ts for access in firebase * Revert "moved calculate ts for access in firebase" This reverts commit 8380bf4f726cdfa0009cc40d6938ad5d65789d30. * fix reference to calculate for firebase * fixed references to time * renamed function * added description * added auto resolution to description * direct bool check instead of != null * direct bool check instead of != undefined * remove explicit type * Fix free response markets * removed contract from functionname * interval set to 1h * query instead of filter * folds ~> contracts * query instead of filter * promise.all instead of foreach * removed contractDoc from function header * removed autoResolution from function header * batchedWaitAll instead of promise.all * removed unused parameter * replaced auto resolution with constant * suggestions from PR * fix comment * removed unused imports * added scripts to add close dates on prod * optimization * removed test script * security: only auto resolve markets which are closed * consistency checks * re-added type check for binary markets * moved check of probability into switch case block * removed unused import * auto resolution every minute * auto resolution time optional * pr fixes
2022-06-14 20:01:32 +00:00
const [open, setOpen] = useState(false)
2022-08-25 13:05:26 +00:00
const [featured, setFeatured] = useState(
(contract?.featuredOnHomeRank ?? 0) > 0
)
const isDev = useDev()
const isAdmin = useAdmin()
2022-10-03 15:26:39 +00:00
const isCreator = user?.id === contract.creatorId
const isUnlisted = contract.visibility === 'unlisted'
2022-10-03 15:36:49 +00:00
const wasUnlistedByCreator = contract.unlistedById
? contract.unlistedById === contract.creatorId
2022-10-03 15:57:27 +00:00
: false
2022-04-09 23:04:13 +00:00
2022-08-28 18:27:51 +00:00
const formatTime = (dt: number) => dayjs(dt).format('MMM DD, YYYY hh:mm a')
2022-09-16 04:08:31 +00:00
const {
createdTime,
closeTime,
resolutionTime,
uniqueBettorCount,
mechanism,
outcomeType,
id,
} = contract
const typeDisplay =
outcomeType === 'BINARY'
? 'YES / NO'
: outcomeType === 'FREE_RESPONSE'
? 'Free response'
: outcomeType === 'MULTIPLE_CHOICE'
? 'Multiple choice'
: 'Numeric'
2022-04-09 23:04:13 +00:00
2022-08-26 02:42:40 +00:00
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
size="sm"
color="gray-white"
className={clsx(contractDetailsButtonClassName, className)}
onClick={() => setOpen(true)}
>
<DotsHorizontalIcon
className={clsx('h-5 w-5 flex-shrink-0')}
aria-hidden="true"
/>
</Button>
<Modal open={open} setOpen={setOpen}>
<Col className="gap-4 rounded bg-white p-6">
<Title className="!mt-0 !mb-0" text="This Market" />
2022-04-09 23:04:13 +00:00
<table className="table-compact table-zebra table w-full text-gray-500">
<tbody>
<tr>
<td>Type</td>
<td>{typeDisplay}</td>
</tr>
<tr>
<td>Payout</td>
2022-08-19 16:53:16 +00:00
<td className="flex gap-1">
{mechanism === 'cpmm-1' ? (
<>
Fixed{' '}
<InfoTooltip text="Each YES share is worth M$1 if YES wins." />
</>
) : (
2022-08-19 16:53:16 +00:00
<>
Parimutuel{' '}
<InfoTooltip text="Each share is a fraction of the pool. " />
2022-08-19 16:53:16 +00:00
</>
)}
</td>
</tr>
2022-04-09 23:04:13 +00:00
<tr>
<td>Market created</td>
<td>{formatTime(createdTime)}</td>
</tr>
{closeTime && (
<tr>
<td>Market close{closeTime > Date.now() ? 's' : 'd'}</td>
<td>{formatTime(closeTime)}</td>
</tr>
)}
{resolutionTime && (
<tr>
<td>Market resolved</td>
<td>{formatTime(resolutionTime)}</td>
</tr>
)}
<tr>
<td>Volume</td>
2022-04-09 23:13:10 +00:00
<td>{formatMoney(contract.volume)}</td>
2022-04-09 23:04:13 +00:00
</tr>
2022-04-13 19:11:49 +00:00
<tr>
2022-09-15 21:51:39 +00:00
<td>{capitalize(BETTORS)}</td>
2022-09-16 04:08:31 +00:00
<td>{uniqueBettorCount ?? '0'}</td>
2022-04-13 19:11:49 +00:00
</tr>
<tr>
<td>
{mechanism === 'cpmm-1' ? 'Liquidity pool' : 'Betting pool'}
</td>
<td>{contractPool(contract)}</td>
</tr>
{/* Show a path to Firebase if user is an admin, or we're on localhost */}
{(isAdmin || isDev) && (
<tr>
2022-08-28 18:30:27 +00:00
<td>[ADMIN] Firestore</td>
<td>
<SiteLink href={firestoreConsolePath(id)}>
Console link
</SiteLink>
</td>
</tr>
)}
2022-08-25 13:05:26 +00:00
{isAdmin && (
<tr>
2022-08-26 02:42:40 +00:00
<td>[ADMIN] Featured</td>
2022-08-25 13:05:26 +00:00
<td>
2022-08-26 02:42:40 +00:00
<ShortToggle
2022-10-03 15:36:49 +00:00
on={featured}
setOn={setFeatured}
2022-08-26 02:42:40 +00:00
onChange={onFeaturedToggle}
/>
2022-08-25 13:05:26 +00:00
</td>
</tr>
)}
2022-10-03 15:36:49 +00:00
{user && (
<tr>
<td>{isAdmin ? '[ADMIN]' : ''} Unlisted</td>
<td>
<ShortToggle
disabled={
isUnlisted
? !(isAdmin || (isCreator && wasUnlistedByCreator))
: !(isCreator || isAdmin)
}
on={contract.visibility === 'unlisted'}
setOn={(b) =>
updateContract(id, {
visibility: b ? 'unlisted' : 'public',
unlistedById: b ? user.id : '',
})
}
/>
</td>
</tr>
)}
2022-04-09 23:04:13 +00:00
</tbody>
</table>
<Row className="flex-wrap">
<DuplicateContractButton contract={contract} />
</Row>
{!contract.resolution && <LiquidityBountyPanel contract={contract} />}
</Col>
</Modal>
</>
)
}