Skip to content

Commit

Permalink
Ingawei/edit mode (#2040)
Browse files Browse the repository at this point in the history
* basic editing working
  • Loading branch information
ingawei committed Sep 17, 2023
1 parent f2ffc78 commit 72ebdfb
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 38 deletions.
2 changes: 2 additions & 0 deletions backend/api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import { getyourdashboards } from './get-your-dashboards'
import { followdashboard } from './follow-dashboard'
import { supabasesearchdashboards } from './supabase-search-dashboards'
import { getyourfolloweddashboards } from './get-your-followed-dashboards'
import { updatedashboard } from './update-dashboard'

const allowCors: RequestHandler = cors({
origin: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_VERCEL, CORS_ORIGIN_LOCALHOST],
Expand Down Expand Up @@ -209,6 +210,7 @@ app.post('/getyourdashboards', ...apiRoute(getyourdashboards))
app.post('/followdashboard', ...apiRoute(followdashboard))
app.post('/supabasesearchdashboards', ...apiRoute(supabasesearchdashboards))
app.post('/getyourfolloweddashboards', ...apiRoute(getyourfolloweddashboards))
app.post('/updatedashboard', ...apiRoute(updatedashboard))

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

const schema = z.object({
dashboardId: z.string(),
items: z.array(DashboardItemSchema),
})

export const updatedashboard = authEndpoint(async (req, auth) => {
const { dashboardId, items } = validate(schema, req.body)

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

const updatedDashboard = await pg.one(
`update dashboards
set items = $1
where id = $2 and creator_id = $3
returning *`,
[JSON.stringify(items), dashboardId, auth.uid]
)

// return updated dashboard
return { updateDashboard: updatedDashboard }
})
7 changes: 5 additions & 2 deletions web/components/contract/contract-description.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,14 @@ function AddAnswerButton(props: {

export function JSONEmpty(text: string | JSONContent) {
if (!text) return true

if (typeof text === 'string') {
return text === ''
} else if ('content' in text) {
return !(text.content && text.content.length > 0 && text.content[0].content)
return !(
!!text.content &&
text.content.length > 0 &&
(!!text.content[0].content || !!text.content[0].attrs)
)
}
return true
}
31 changes: 31 additions & 0 deletions web/components/dashboard/add-dashboard-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
DashboardItem,
DashboardLinkItem,
DashboardQuestionItem,
} from 'common/dashboard'
import { Row } from '../layout/row'
import { DashboardAddContractButton } from './dashboard-add-contract-button'
import { DashboardAddLinkButton } from './dashboard-add-link-button'

export function AddDashboardItemWidget(props: {
items: DashboardItem[]
setItems: (items: DashboardItem[]) => void
}) {
const { items, setItems } = props

return (
<Row className="border-ink-200 text-ink-400 items-center gap-4 rounded-lg border-2 border-dashed p-2">
<DashboardAddContractButton
addQuestions={(questions: DashboardQuestionItem[]) => {
setItems([...items, ...questions])
}}
/>
OR
<DashboardAddLinkButton
addLink={(link: DashboardLinkItem) => {
setItems([...items, link])
}}
/>
</Row>
)
}
15 changes: 6 additions & 9 deletions web/components/dashboard/dashboard-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { JSONContent } from '@tiptap/core'
import { JSONEmpty } from '../contract/contract-description'
import { Col } from '../layout/col'
import { Content } from '../widgets/editor'
import { Content, TextEditor, useTextEditor } from '../widgets/editor'
import clsx from 'clsx'
import { MAX_DESCRIPTION_LENGTH } from 'common/contract'

export const DashboardSidebar = (props: {
description?: JSONContent
Expand All @@ -14,18 +15,14 @@ export const DashboardSidebar = (props: {

return (
<Col className={clsx(inSidebar ? 'hidden xl:inline-flex' : 'xl:hidden')}>
{description && (
{inSidebar && (
<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 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 @@ -516,3 +516,10 @@ export function supabaseSearchDashboards(params: {
export function getYourFollowedDashboards() {
return call(getApiUrl('getyourfolloweddashboards'), 'POST')
}

export function updateDashboard(params: {
dashboardId: string
items: DashboardItem[]
}) {
return call(getApiUrl('updatedashboard'), 'POST', params)
}
90 changes: 81 additions & 9 deletions web/pages/dashboard/[dashboardSlug].tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { Dashboard, DashboardItem } from 'common/dashboard'
import { getDashboardFromSlug } from 'common/supabase/dashboard'
import { useState } from 'react'
import { Button } from 'web/components/buttons/button'
import { AddDashboardItemWidget } from 'web/components/dashboard/add-dashboard-item'
import { DashboardContent } from 'web/components/dashboard/dashboard-content'
import { DashboardSidebar } from 'web/components/dashboard/dashboard-sidebar'
import { FollowDashboardButton } from 'web/components/dashboard/follow-dashboard-button'
import { Col } from 'web/components/layout/col'
import { Page } from 'web/components/layout/page'
import { Row } from 'web/components/layout/row'
import { Avatar } from 'web/components/widgets/avatar'
import { Title } from 'web/components/widgets/title'
import { UserLink } from 'web/components/widgets/user-link'
import { useUser } from 'web/hooks/use-user'
import { updateDashboard } from 'web/lib/firebase/api'
import { initSupabaseAdmin } from 'web/lib/supabase/admin-db'
import Custom404 from '../404'

export async function getStaticProps(ctx: {
params: { dashboardSlug: string }
Expand All @@ -22,7 +28,7 @@ export async function getStaticProps(ctx: {
dashboardSlug,
adminDb
)
return { props: { dashboard } }
return { props: { initialDashboard: dashboard } }
} catch (e) {
if (typeof e === 'object' && e !== null && 'code' in e && e.code === 404) {
return {
Expand All @@ -38,10 +44,17 @@ export async function getStaticPaths() {
return { paths: [], fallback: 'blocking' }
}

export default function DashboardPage(props: { dashboard: Dashboard }) {
const { dashboard } = props
const [items, setItems] = useState<DashboardItem[]>(dashboard.items)
export default function DashboardPage(props: { initialDashboard: Dashboard }) {
const { initialDashboard } = props
const [dashboard, setDashboard] = useState<Dashboard>(initialDashboard)
const [items, setItems] = useState<DashboardItem[]>(dashboard?.items)
const user = useUser()
const canEdit = dashboard.creator_id === user?.id
const [editMode, setEditMode] = useState(false)
if (!dashboard) {
return <Custom404 />
}

return (
<Page
trackPageView={'dashboard slug page'}
Expand All @@ -52,13 +65,32 @@ export default function DashboardPage(props: { dashboard: Dashboard }) {
>
<Col className="items-center">
<Col className="w-full max-w-2xl px-1 sm:px-2">
<Row className="w-full items-center justify-between">
<Title className="mt-4">{dashboard.title}</Title>
<FollowDashboardButton
dashboardId={dashboard.id}
dashboardCreatorId={dashboard.creator_id}
<Row className="gap-2">
<Avatar
username={dashboard.creator_username}
avatarUrl={dashboard.creator_avatar_url}
size="xs"
/>
<UserLink
username={dashboard.creator_username}
name={dashboard.creator_name}
/>
</Row>
<Row className="w-full items-center justify-between">
<Title>{dashboard.title}</Title>
<Row>
<FollowDashboardButton
dashboardId={dashboard.id}
dashboardCreatorId={dashboard.creator_id}
/>
{canEdit && !editMode && (
<Button onClick={() => setEditMode((editMode) => !editMode)}>
Edit
</Button>
)}
</Row>
</Row>

<DashboardSidebar description={dashboard.description} />
<DashboardContent
items={items}
Expand All @@ -74,7 +106,47 @@ export default function DashboardPage(props: { dashboard: Dashboard }) {
})
})
}}
isEditing={editMode}
/>
{editMode && (
<Col className="gap-4">
<AddDashboardItemWidget items={items} setItems={setItems} />
<Row className="w-full justify-end gap-2">
<Button
color="gray"
onClick={() => {
setItems(dashboard.items)
setEditMode(false)
}}
>
Cancel
</Button>
<Button
disabled={items.length < 2}
onClick={() => {
if (items !== dashboard.items) {
updateDashboard({
dashboardId: dashboard.id,
items,
}).then((resultingDashboard) => {
if (
resultingDashboard &&
resultingDashboard.updateDashboard
) {
setDashboard(
resultingDashboard.updateDashboard as Dashboard
)
}
})
}
setEditMode(false)
}}
>
Save
</Button>
</Row>
</Col>
)}
</Col>
</Col>
</Page>
Expand Down
19 changes: 4 additions & 15 deletions web/pages/dashboard/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import router from 'next/router'
import { useEffect, useState } from 'react'
import { SEO } from 'web/components/SEO'
import { Button } from 'web/components/buttons/button'
import { AddDashboardItemWidget } from 'web/components/dashboard/add-dashboard-item'
import { DashboardAddContractButton } from 'web/components/dashboard/dashboard-add-contract-button'
import { DashboardAddLinkButton } from 'web/components/dashboard/dashboard-add-link-button'
import { DashboardContent } from 'web/components/dashboard/dashboard-content'
Expand All @@ -31,7 +32,7 @@ export default function CreateDashboard() {
)

const editor = useTextEditor({
key: 'create dashbord dsecription',
key: 'create dashbord description',
max: MAX_DESCRIPTION_LENGTH,
placeholder: 'Optional. Provide background info and details.',
})
Expand All @@ -47,7 +48,7 @@ export default function CreateDashboard() {
'create dashboard items'
)

const isValid = title.length > 0
const isValid = title.length > 0 && items.length > 1

useEffect(() => {
setErrorText('')
Expand Down Expand Up @@ -143,19 +144,7 @@ export default function CreateDashboard() {
isEditing
/>
)}
<Row className="border-ink-200 text-ink-400 items-center gap-4 rounded-lg border-2 border-dashed p-2">
<DashboardAddContractButton
addQuestions={(questions: DashboardQuestionItem[]) => {
setItems((items) => [...items, ...questions])
}}
/>
OR
<DashboardAddLinkButton
addLink={(link: DashboardLinkItem) => {
setItems((items) => [...items, link])
}}
/>
</Row>
<AddDashboardItemWidget items={items} setItems={setItems} />
<Spacer h={6} />
<span className={'text-error'}>{errorText}</span>
<Button
Expand Down
3 changes: 0 additions & 3 deletions web/pages/dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export default function DashboardPage() {
useRedirectIfSignedOut()
const user = useUser()

if (!DASHBOARD_ENABLED) {
return <Custom404 />
}
return (
<Page trackPageView={'dashboards page'}>
<Col className="items-center">
Expand Down

3 comments on commit 72ebdfb

@vercel
Copy link

@vercel vercel bot commented on 72ebdfb Sep 17, 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-mantic.vercel.app
docs-pi-teal.vercel.app
docs-git-main-mantic.vercel.app
docs.manifold.markets

@vercel
Copy link

@vercel vercel bot commented on 72ebdfb Sep 17, 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 72ebdfb Sep 17, 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.