Skip to content

Commit

Permalink
static props is backup for dashboard (#2042)
Browse files Browse the repository at this point in the history
  • Loading branch information
ingawei committed Sep 18, 2023
1 parent 1a6423f commit ad0277c
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 19 deletions.
2 changes: 2 additions & 0 deletions backend/api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import { followdashboard } from './follow-dashboard'
import { supabasesearchdashboards } from './supabase-search-dashboards'
import { getyourfolloweddashboards } from './get-your-followed-dashboards'
import { updatedashboard } from './update-dashboard'
import { getdashboardfromslug } from './get-dashboard-from-slug'

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

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

const bodySchema = z.object({
dashboardSlug: z.string(),
})

export const getdashboardfromslug = MaybeAuthedEndpoint(async (req) => {
const { dashboardSlug } = validate(bodySchema, req.body)
const db = createSupabaseClient()
const { data } = await run(
db.from('dashboards').select('*').eq('slug', dashboardSlug).limit(1)
)

if (data && data.length > 0) {
return { dashboard: data[0] }
}
return { dashboard: null }
})
14 changes: 12 additions & 2 deletions web/components/dashboard/dashboard-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@ import { DashboardNewsItem } from '../news/dashboard-news-item'
import { FeedContractCard } from '../contract/feed-contract-card'
import { Col } from '../layout/col'
import { LoadingIndicator } from '../widgets/loading-indicator'
import { ReactNode } from 'react'
import { ReactNode, useState } from 'react'
import { XCircleIcon } from '@heroicons/react/solid'
import { DashboardItem } from 'common/dashboard'
import { Dashboard, DashboardItem } from 'common/dashboard'
import { useUser } from 'web/hooks/use-user'
import { Row } from '../layout/row'
import { Avatar } from '../widgets/avatar'
import { UserLink } from '../widgets/user-link'
import { Title } from '../widgets/title'
import { FollowDashboardButton } from './follow-dashboard-button'
import { Button } from '../buttons/button'
import { DashboardSidebar } from './dashboard-sidebar'
import { AddDashboardItemWidget } from './add-dashboard-item'
import { updateDashboard } from 'web/lib/firebase/api'

export const DashboardContent = (props: {
items: DashboardItem[]
Expand Down
16 changes: 15 additions & 1 deletion web/hooks/use-dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { useEffect, useState } from 'react'
import { useIsAuthorized } from './use-user'
import { Dashboard } from 'common/dashboard'
import { getYourDashboards } from 'web/lib/firebase/api'
import { getDashboardFromSlug, getYourDashboards } from 'web/lib/firebase/api'
import { getYourFollowedDashboards } from 'web/lib/firebase/api'

export function useDashboardFromSlug(slug: string) {
const [dashboard, setDashboard] = useState<Dashboard | undefined | null>(
undefined
)

useEffect(() => {
getDashboardFromSlug({ dashboardSlug: slug }).then((result) => {
setDashboard(result.dashboard as Dashboard)
})
}, [slug])

return dashboard
}

export function useYourDashboards() {
const isAuth = useIsAuthorized()

Expand Down
4 changes: 4 additions & 0 deletions web/lib/firebase/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,3 +522,7 @@ export function updateDashboard(params: {
}) {
return call(getApiUrl('updatedashboard'), 'POST', params)
}

export function getDashboardFromSlug(params: { dashboardSlug: string }) {
return call(getApiUrl('getdashboardfromslug'), 'POST', params)
}
65 changes: 49 additions & 16 deletions web/pages/dashboard/[dashboardSlug].tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Dashboard, DashboardItem } from 'common/dashboard'
import { getDashboardFromSlug } from 'common/supabase/dashboard'
import { useState } from 'react'
import { use, useEffect, 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'
Expand All @@ -16,6 +16,8 @@ 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'
import { useDashboardFromSlug } from 'web/hooks/use-dashboard'
import { update } from '@react-spring/web'

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

export default function DashboardPage(props: { initialDashboard: Dashboard }) {
const { initialDashboard } = props
const [dashboard, setDashboard] = useState<Dashboard>(initialDashboard)
const [items, setItems] = useState<DashboardItem[]>(dashboard?.items)
export default function DashboardPage(props: {
initialDashboard: Dashboard
slug: string
}) {
const { initialDashboard, slug } = props
const fetchedDashboard = useDashboardFromSlug(slug)
const [dashboard, setDashboard] = useState<Dashboard>(
fetchedDashboard ?? initialDashboard
)

// Update the dashboard state if a new fetchedDashboard becomes available
useEffect(() => {
if (fetchedDashboard) {
setDashboard(fetchedDashboard)
}
}, [fetchedDashboard])

const updateItems = (newItems: DashboardItem[]) => {
if (dashboard) {
const updatedDashboard = { ...dashboard, items: newItems }
setDashboard(updatedDashboard)
}
}

const user = useUser()
const canEdit = dashboard.creator_id === user?.id
const [editMode, setEditMode] = useState(false)
Expand Down Expand Up @@ -93,41 +115,52 @@ export default function DashboardPage(props: { initialDashboard: Dashboard }) {

<DashboardSidebar description={dashboard.description} />
<DashboardContent
items={items}
items={dashboard.items}
onRemove={(slugOrUrl: string) => {
setItems((items) => {
return items.filter((item) => {
updateItems(
dashboard.items.filter((item) => {
if (item.type === 'question') {
return item.slug !== slugOrUrl
} else if (item.type === 'link') {
return item.url !== slugOrUrl
}
return true
})
})
)
}}
isEditing={editMode}
/>
{editMode && (
<Col className="gap-4">
<AddDashboardItemWidget items={items} setItems={setItems} />
<AddDashboardItemWidget
items={dashboard.items}
setItems={updateItems}
/>
<Row className="w-full justify-end gap-2">
<Button
color="gray"
onClick={() => {
setItems(dashboard.items)
// reset items to original state
updateItems(
fetchedDashboard
? fetchedDashboard.items
: initialDashboard.items
)
setEditMode(false)
}}
>
Cancel
</Button>
<Button
disabled={items.length < 2}
disabled={dashboard.items.length < 2}
onClick={() => {
if (items !== dashboard.items) {
if (
dashboard !== fetchedDashboard &&
dashboard !== initialDashboard
) {
updateDashboard({
dashboardId: dashboard.id,
items,
items: dashboard.items,
}).then((resultingDashboard) => {
if (
resultingDashboard &&
Expand All @@ -138,8 +171,8 @@ export default function DashboardPage(props: { initialDashboard: Dashboard }) {
)
}
})
setEditMode(false)
}
setEditMode(false)
}}
>
Save
Expand Down

2 comments on commit ad0277c

@vercel
Copy link

@vercel vercel bot commented on ad0277c Sep 18, 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-pi-teal.vercel.app
docs.manifold.markets
docs-mantic.vercel.app

@vercel
Copy link

@vercel vercel bot commented on ad0277c Sep 18, 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.