forked from manifoldmarkets/manifold
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Fold type, fold page, query for fold contracts * Tsconfig: target esnext, nounused locals: false * Store tags in field on contract. Script to update contract tags * Show tags on fold page * Load all fold comments server-side to serve better feed * Fix the annoying firebase already initialized error! * Add links to /edit and /leaderboards for fold * Page with list of folds * UI for creating a fold * Create a fold * Edit fold page
- Loading branch information
Showing
30 changed files
with
832 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export type Fold = { | ||
id: string | ||
slug: string | ||
name: string | ||
curatorId: string // User id | ||
createdTime: number | ||
|
||
tags: string[] | ||
|
||
contractIds: string[] | ||
excludedContractIds: string[] | ||
|
||
// Invariant: exactly one of the following is defined. | ||
// Default: creatorIds: undefined, excludedCreatorIds: [] | ||
creatorIds?: string[] | ||
excludedCreatorIds?: string[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export function parseTags(text: string) { | ||
const regex = /(?:^|\s)(?:[#][a-z0-9_]+)/gi | ||
const matches = (text.match(regex) || []).map((match) => | ||
match.trim().substring(1) | ||
) | ||
const tagSet = new Set(matches) | ||
const uniqueTags: string[] = [] | ||
tagSet.forEach((tag) => uniqueTags.push(tag)) | ||
return uniqueTags | ||
} | ||
|
||
export function parseWordsAsTags(text: string) { | ||
const regex = /(?:^|\s)(?:[a-z0-9_]+)/gi | ||
const matches = (text.match(regex) || []) | ||
.map((match) => match.trim()) | ||
.filter((tag) => tag) | ||
const tagSet = new Set(matches) | ||
const uniqueTags: string[] = [] | ||
tagSet.forEach((tag) => uniqueTags.push(tag)) | ||
return uniqueTags | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import * as functions from 'firebase-functions' | ||
import * as admin from 'firebase-admin' | ||
import * as _ from 'lodash' | ||
|
||
import { getUser } from './utils' | ||
import { Contract } from '../../common/contract' | ||
import { slugify } from '../../common/util/slugify' | ||
import { randomString } from '../../common/util/random' | ||
import { Fold } from '../../common/fold' | ||
|
||
export const createFold = functions.runWith({ minInstances: 1 }).https.onCall( | ||
async ( | ||
data: { | ||
name: string | ||
tags: string[] | ||
}, | ||
context | ||
) => { | ||
const userId = context?.auth?.uid | ||
if (!userId) return { status: 'error', message: 'Not authorized' } | ||
|
||
const creator = await getUser(userId) | ||
if (!creator) return { status: 'error', message: 'User not found' } | ||
|
||
const { name, tags } = data | ||
|
||
if (!name || typeof name !== 'string') | ||
return { status: 'error', message: 'Name must be a non-empty string' } | ||
|
||
if (!_.isArray(tags)) | ||
return { status: 'error', message: 'Tags must be an array of strings' } | ||
|
||
console.log( | ||
'creating fold for', | ||
creator.username, | ||
'named', | ||
name, | ||
'on', | ||
tags | ||
) | ||
|
||
const slug = await getSlug(name) | ||
|
||
const foldRef = firestore.collection('folds').doc() | ||
|
||
const fold: Fold = { | ||
id: foldRef.id, | ||
curatorId: userId, | ||
slug, | ||
name, | ||
tags, | ||
createdTime: Date.now(), | ||
contractIds: [], | ||
excludedContractIds: [], | ||
excludedCreatorIds: [], | ||
} | ||
|
||
await foldRef.create(fold) | ||
|
||
return { status: 'success', fold } | ||
} | ||
) | ||
|
||
const getSlug = async (name: string) => { | ||
const proposedSlug = slugify(name) | ||
|
||
const preexistingFold = await getFoldFromSlug(proposedSlug) | ||
|
||
return preexistingFold ? proposedSlug + '-' + randomString() : proposedSlug | ||
} | ||
|
||
const firestore = admin.firestore() | ||
|
||
export async function getFoldFromSlug(slug: string) { | ||
const snap = await firestore | ||
.collection('folds') | ||
.where('slug', '==', slug) | ||
.get() | ||
|
||
return snap.empty ? undefined : (snap.docs[0].data() as Contract) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import * as admin from 'firebase-admin' | ||
import * as _ from 'lodash' | ||
|
||
// Generate your own private key, and set the path below: | ||
// https://console.firebase.google.com/u/0/project/mantic-markets/settings/serviceaccounts/adminsdk | ||
// James: | ||
const serviceAccount = require('/Users/jahooma/mantic-markets-firebase-adminsdk-1ep46-820891bb87.json') | ||
// Stephen: | ||
// const serviceAccount = require('../../../../Downloads/dev-mantic-markets-firebase-adminsdk-sir5m-b2d27f8970.json') | ||
admin.initializeApp({ | ||
credential: admin.credential.cert(serviceAccount), | ||
}) | ||
const firestore = admin.firestore() | ||
|
||
import { Contract } from '../../../common/contract' | ||
import { parseTags } from '../../../common/util/parse' | ||
import { getValues } from '../utils' | ||
|
||
async function updateContractTags() { | ||
console.log('Updating contracts tags') | ||
|
||
const contracts = await getValues<Contract>(firestore.collection('contracts')) | ||
|
||
console.log('Loaded', contracts.length, 'contracts') | ||
|
||
for (const contract of contracts) { | ||
const contractRef = firestore.doc(`contracts/${contract.id}`) | ||
|
||
const tags = _.uniq([ | ||
...parseTags(contract.question + contract.description), | ||
...(contract.tags ?? []), | ||
]) | ||
|
||
console.log( | ||
'Updating tags', | ||
contract.slug, | ||
'from', | ||
contract.tags, | ||
'to', | ||
tags | ||
) | ||
|
||
await contractRef.update({ | ||
tags, | ||
} as Partial<Contract>) | ||
} | ||
} | ||
|
||
if (require.main === module) updateContractTags().then(() => process.exit()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import Image from 'next/image' | ||
import { User } from '../../common/user' | ||
import { Row } from './layout/row' | ||
import { SiteLink } from './site-link' | ||
import { Title } from './title' | ||
|
||
export function Leaderboard(props: { | ||
title: string | ||
users: User[] | ||
columns: { | ||
header: string | ||
renderCell: (user: User) => any | ||
}[] | ||
}) { | ||
const { title, users, columns } = props | ||
return ( | ||
<div className="max-w-xl w-full px-1"> | ||
<Title text={title} /> | ||
<div className="overflow-x-auto"> | ||
<table className="table table-zebra table-compact text-gray-500 w-full"> | ||
<thead> | ||
<tr className="p-2"> | ||
<th>#</th> | ||
<th>Name</th> | ||
{columns.map((column) => ( | ||
<th key={column.header}>{column.header}</th> | ||
))} | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{users.map((user, index) => ( | ||
<tr key={user.id}> | ||
<td>{index + 1}</td> | ||
<td> | ||
<SiteLink className="relative" href={`/${user.username}`}> | ||
<Row className="items-center gap-4"> | ||
<Image | ||
className="rounded-full bg-gray-400 flex-shrink-0 ring-8 ring-gray-50" | ||
src={user.avatarUrl || ''} | ||
alt="" | ||
width={32} | ||
height={32} | ||
/> | ||
<div>{user.name}</div> | ||
</Row> | ||
</SiteLink> | ||
</td> | ||
{columns.map((column) => ( | ||
<td key={column.header}>{column.renderCell(user)}</td> | ||
))} | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Row } from './layout/row' | ||
import { Linkify } from './linkify' | ||
|
||
export function TagsList(props: { tags: string[] }) { | ||
const { tags } = props | ||
return ( | ||
<Row className="gap-2 flex-wrap text-sm text-gray-500"> | ||
{tags.map((tag) => ( | ||
<div key={tag} className="bg-gray-100 px-1"> | ||
<Linkify text={tag} gray /> | ||
</div> | ||
))} | ||
</Row> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.