Skip to content

Commit

Permalink
dashboard starting (#2018)
Browse files Browse the repository at this point in the history
* dashboard starting
  • Loading branch information
ingawei committed Sep 8, 2023
1 parent 4828dac commit e902e42
Show file tree
Hide file tree
Showing 14 changed files with 358 additions and 16 deletions.
3 changes: 3 additions & 0 deletions backend/api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { castpollvote } from './cast-poll-vote'
import { getsimilargroupstocontract } from 'api/get-similar-groups-to-contract'
import { followUser } from './follow-user'
import { report } from './report'
import { createdashboard } from './create-dashboard'

const allowCors: RequestHandler = cors({
origin: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_VERCEL, CORS_ORIGIN_LOCALHOST],
Expand Down Expand Up @@ -205,6 +206,8 @@ app.post('/claimdestinysub', ...apiRoute(claimdestinysub))
app.post('/follow-user', ...apiRoute(followUser))
app.post('/report', ...apiRoute(report))

app.post('/createdashboard', ...apiRoute(createdashboard))

// Catch 404 errors - this should be the last route
app.use(allowCors, (req, res) => {
res
Expand Down
40 changes: 40 additions & 0 deletions backend/api/src/create-dashboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createSupabaseDirectClient } from 'shared/supabase/init'
import { log } from 'shared/utils'
import { z } from 'zod'
import { APIError, authEndpoint, validate } from './helpers'
import { contentSchema } from 'shared/zod-types'
import { slugify } from 'common/util/slugify'
import { randomString } from 'common/util/random'

const schema = z.object({
title: z.string(),
description: contentSchema.optional(),
})

export const createdashboard = authEndpoint(async (req, auth) => {
const { title, description } = validate(schema, req.body)

log('creating dashboard')
const pg = createSupabaseDirectClient()

let slug = slugify(title)
const data = await pg.manyOrNone(
`select slug from dashboards where slug = $1`,
[slug]
)

if (data && data.length > 0) {
slug = `${slug}-${randomString(8)}`
}

// create if not exists the group invite link row
const { id } = await pg.one(
`insert into dashboards(slug, creator_id, description, title)
values ($1, $2, $3,$4)
returning id, slug`,
[slug, auth.uid, description, title]
)

// return something
return { id: id, slug: slug }
})
11 changes: 11 additions & 0 deletions backend/supabase/dashboards/create.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
create table if not exists
dashboards (
id text not null primary key default random_alphanumeric (12),
slug text not null unique,
creator_id text not null,
foreign key (creator_id) references users (id),
created_time timestamptz not null default now(),
views numeric not null default 0,
description json,
title text not null
);
11 changes: 11 additions & 0 deletions common/src/dashboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { JSONContent } from '@tiptap/core'

export type Dashboard = {
id: string
slug: string
creator_id: string
created_time: number
views: number
description: JSONContent
title: string
}
2 changes: 2 additions & 0 deletions common/src/envs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const CONFIGS: { [env: string]: EnvConfig } = {
DEV: DEV_CONFIG,
}

export const DASHBOARD_ENABLED = ENV === 'DEV'

export const ENV_CONFIG = CONFIGS[ENV]

export function isAdminId(id: string) {
Expand Down
13 changes: 13 additions & 0 deletions common/src/supabase/dashboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SupabaseClient } from '@supabase/supabase-js'
import { run } from './utils'

export async function getDashboardFromSlug(slug: string, db: SupabaseClient) {
const { data: dashboard } = await run(
db.from('dashboards').select('*').eq('slug', slug).limit(1)
)

if (dashboard && dashboard.length > 0) {
return dashboard[0]
}
return null
}
20 changes: 7 additions & 13 deletions web/components/contract/contract-description.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { CollapsibleContent } from '../widgets/collapsible-content'
import { isTrustworthy } from 'common/envs/constants'
import { ContractEditHistoryButton } from 'web/components/contract/contract-edit-history-button'
import { PencilIcon, PlusIcon } from '@heroicons/react/solid'
import { Editor } from '@tiptap/core'
import { Editor, JSONContent } from '@tiptap/core'
import { CreateAnswerCpmmPanel } from '../answers/create-answer-panel'

export function ContractDescription(props: {
Expand Down Expand Up @@ -224,19 +224,13 @@ function AddAnswerButton(props: {
)
}

export function descriptionIsEmpty(contract: Contract) {
const description = contract.description
export function JSONEmpty(text: string | JSONContent) {
if (!text) return true

if (!description) return true

if (typeof description === 'string') {
return description === ''
} else if ('content' in description) {
return !(
description.content &&
description.content.length > 0 &&
description.content[0].content
)
if (typeof text === 'string') {
return text === ''
} else if ('content' in text) {
return !(text.content && text.content.length > 0 && text.content[0].content)
}
return true
}
5 changes: 2 additions & 3 deletions web/components/contract/feed-contract-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ import { Col } from '../layout/col'
import { Row } from '../layout/row'
import { PollPanel } from '../poll/poll-panel'
import { ClickFrame } from '../widgets/click-frame'
import { descriptionIsEmpty } from './contract-description'
import { LikeButton } from './like-button'
import { TradesButton } from './trades-button'
import { FeedDropdown } from '../feed/card-dropdown'
import { GroupTags } from '../feed/feed-timeline-items'
import { JSONEmpty } from './contract-description'

export function FeedContractCard(props: {
contract: Contract
Expand Down Expand Up @@ -229,8 +229,7 @@ export function FeedContractCard(props: {
<YourMetricsFooter metrics={metrics} />
)}

{!descriptionIsEmpty(contract) &&
!small &&
{!JSONEmpty(contract.description) &&
(item?.dataType == 'new_contract' || nonTextDescription) && (
<FeedContractCardDescription
contract={contract}
Expand Down
16 changes: 16 additions & 0 deletions web/components/dashboard/create-dashboard-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import clsx from 'clsx'
import Link from 'next/link'
import { buttonClass } from '../buttons/button'

export function CreateDashboardButton() {
return (
<>
<Link
href="/dashboard/create"
className={clsx(buttonClass('md', 'indigo'))}
>
Create a dashboard
</Link>
</>
)
}
31 changes: 31 additions & 0 deletions web/components/dashboard/dashboard-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { JSONContent } from '@tiptap/core'
import { JSONEmpty } from '../contract/contract-description'
import { Col } from '../layout/col'
import { Content } from '../widgets/editor'
import clsx from 'clsx'

export const DashboardSidebar = (props: {
description?: JSONContent
inSidebar?: boolean
}) => {
const { description, inSidebar } = props

if (!description || JSONEmpty(description)) return <></>

return (
<Col className={clsx(inSidebar ? 'hidden xl:inline-flex' : 'xl:hidden')}>
{description && (
<Col className=" text-primary-700 mb-2 hidden xl:inline-flex">
Additional Context
</Col>
)}
{description && (
<>
<Col className="bg-canvas-0 mb-4 gap-2 py-2 px-4 xl:px-6 xl:py-4">
<Content content={description} />
</Col>
</>
)}
</Col>
)
}
7 changes: 7 additions & 0 deletions web/lib/firebase/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,3 +471,10 @@ export function unfollowUser(userId: string) {
export function report(params: ReportProps) {
return call(getApiUrl('report'), 'POST', params)
}

export function createDashboard(params: {
title: string
description?: JSONContent
}) {
return call(getApiUrl('createdashboard'), 'POST', params)
}
50 changes: 50 additions & 0 deletions web/pages/dashboard/[dashboardSlug].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Dashboard } from 'common/dashboard'
import { getDashboardFromSlug } from 'common/supabase/dashboard'
import { DashboardSidebar } from 'web/components/dashboard/dashboard-sidebar'
import { Col } from 'web/components/layout/col'
import { Page } from 'web/components/layout/page'
import { NewsSidebar } from 'web/components/news/news-dashboard'
import { Content } from 'web/components/widgets/editor'
import { Title } from 'web/components/widgets/title'
import { db } from 'web/lib/supabase/db'

export async function getStaticProps(ctx: {
params: { dashboardSlug: string }
}) {
const { dashboardSlug } = ctx.params

try {
const dashboard: Dashboard = await getDashboardFromSlug(dashboardSlug, db)
return { props: { dashboard } }
} catch (e) {
if (typeof e === 'object' && e !== null && 'code' in e && e.code === 404) {
return {
props: { state: 'not found' },
revalidate: 60,
}
}
throw e
}
}

export async function getStaticPaths() {
return { paths: [], fallback: 'blocking' }
}

export default function DashboardPage(props: { dashboard: Dashboard }) {
const { dashboard } = props
return (
<Page
rightSidebar={
<DashboardSidebar description={dashboard.description} inSidebar />
}
>
<Col className="items-center">
<Col className="w-full max-w-2xl px-1 sm:px-2">
<Title className="mt-4">{dashboard.title}</Title>
<DashboardSidebar description={dashboard.description} />
</Col>
</Col>
</Page>
)
}

3 comments on commit e902e42

@vercel
Copy link

@vercel vercel bot commented on e902e42 Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./docs

docs-git-main-mantic.vercel.app
docs-mantic.vercel.app
docs-pi-teal.vercel.app
docs.manifold.markets

@vercel
Copy link

@vercel vercel bot commented on e902e42 Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

dev – ./web

dev-git-main-mantic.vercel.app
dev-mantic.vercel.app
dev-manifold.vercel.app
dev.manifold.markets

@vercel
Copy link

@vercel vercel bot commented on e902e42 Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.