Various nit fixes.
This commit is contained in:
parent
760a112c3b
commit
9c3b3920ef
|
@ -9,4 +9,4 @@ export type Dashboard = {
|
||||||
slug: string
|
slug: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MAX_DASHBOARD_NAME_LENGTH = 75
|
export const MAX_DASHBOARD_NAME_LENGTH = 480
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
|
|
||||||
import { getUser } from './utils'
|
import { getUser } from './utils'
|
||||||
import { Contract } from '../../common/contract'
|
|
||||||
import { slugify } from '../../common/util/slugify'
|
import { slugify } from '../../common/util/slugify'
|
||||||
import { randomString } from '../../common/util/random'
|
import { randomString } from '../../common/util/random'
|
||||||
import { Dashboard, MAX_DASHBOARD_NAME_LENGTH } from '../../common/dashboard'
|
import { Dashboard, MAX_DASHBOARD_NAME_LENGTH } from '../../common/dashboard'
|
||||||
|
@ -45,7 +44,7 @@ export const createdashboard = newEndpoint({}, async (req, auth) => {
|
||||||
if (!creator)
|
if (!creator)
|
||||||
throw new APIError(400, 'No user exists with the authenticated user ID.')
|
throw new APIError(400, 'No user exists with the authenticated user ID.')
|
||||||
|
|
||||||
console.log('creating dashboard for', creator.username, 'named', name)
|
console.log('creating dashboard owned by', creator.username, 'named', name)
|
||||||
|
|
||||||
const slug = await getSlug(name)
|
const slug = await getSlug(name)
|
||||||
|
|
||||||
|
@ -82,5 +81,5 @@ export async function getDashboardFromSlug(slug: string) {
|
||||||
.where('slug', '==', slug)
|
.where('slug', '==', slug)
|
||||||
.get()
|
.get()
|
||||||
|
|
||||||
return snap.empty ? undefined : (snap.docs[0].data() as Contract)
|
return snap.empty ? undefined : (snap.docs[0].data() as Dashboard)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,11 @@ export function FileUploadButton(props: {
|
||||||
const ref = useRef<HTMLInputElement>(null)
|
const ref = useRef<HTMLInputElement>(null)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button className={className} onClick={() => ref.current?.click()}>
|
<button
|
||||||
|
type={'button'}
|
||||||
|
className={className}
|
||||||
|
onClick={() => ref.current?.click()}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
<input
|
<input
|
||||||
|
|
|
@ -31,7 +31,7 @@ export function ShareDashboardModal(props: {
|
||||||
toast.success('Link copied!', {
|
toast.success('Link copied!', {
|
||||||
icon: linkIcon,
|
icon: linkIcon,
|
||||||
})
|
})
|
||||||
track('copy share link')
|
track('copy share dashboard link')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{linkIcon} Copy link
|
{linkIcon} Copy link
|
||||||
|
|
|
@ -33,6 +33,5 @@ export function getDashboard(dashboardId: string) {
|
||||||
export async function getDashboardBySlug(slug: string) {
|
export async function getDashboardBySlug(slug: string) {
|
||||||
const q = query(dashboards, where('slug', '==', slug))
|
const q = query(dashboards, where('slug', '==', slug))
|
||||||
const docs = (await getDocs(q)).docs
|
const docs = (await getDocs(q)).docs
|
||||||
console.log(docs.length === 0 ? null : docs[0].data())
|
|
||||||
return docs.length === 0 ? null : docs[0].data()
|
return docs.length === 0 ? null : docs[0].data()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,26 +4,25 @@ import { Page } from 'web/components/page'
|
||||||
import { Title } from 'web/components/title'
|
import { Title } from 'web/components/title'
|
||||||
import Textarea from 'react-expanding-textarea'
|
import Textarea from 'react-expanding-textarea'
|
||||||
|
|
||||||
import { useTracking } from 'web/hooks/use-tracking'
|
|
||||||
import { TextEditor, useTextEditor } from 'web/components/editor'
|
import { TextEditor, useTextEditor } from 'web/components/editor'
|
||||||
import { createDashboard } from 'web/lib/firebase/api'
|
import { createDashboard } from 'web/lib/firebase/api'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { Dashboard } from 'common/dashboard'
|
import { Dashboard, MAX_DASHBOARD_NAME_LENGTH } from 'common/dashboard'
|
||||||
import { dashboardPath } from 'web/lib/firebase/dashboards'
|
import { dashboardPath } from 'web/lib/firebase/dashboards'
|
||||||
|
|
||||||
export default function CreateDashboard() {
|
export default function CreateDashboard() {
|
||||||
useTracking('view create dashboards page')
|
|
||||||
const [name, setName] = useState('')
|
const [name, setName] = useState('')
|
||||||
|
const [error, setError] = useState('')
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const { editor, upload } = useTextEditor({
|
const { editor, upload } = useTextEditor({
|
||||||
max: 1000,
|
|
||||||
defaultValue: '',
|
|
||||||
disabled: isSubmitting,
|
disabled: isSubmitting,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isValid = editor && name.length > 0 && editor.isEmpty === false
|
||||||
|
|
||||||
async function saveDashboard(name: string) {
|
async function saveDashboard(name: string) {
|
||||||
if (!editor) return
|
if (!editor) return
|
||||||
const newDashboard = {
|
const newDashboard = {
|
||||||
|
@ -32,11 +31,13 @@ export default function CreateDashboard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await createDashboard(newDashboard).catch((e) => {
|
const result = await createDashboard(newDashboard).catch((e) => {
|
||||||
console.error(e)
|
console.log(e)
|
||||||
|
setError('There was an error creating the dashboard, please try again')
|
||||||
return e
|
return e
|
||||||
})
|
})
|
||||||
console.log(result.dashboard as Dashboard)
|
if (result.dashboard) {
|
||||||
await router.push(dashboardPath((result.dashboard as Dashboard).slug))
|
await router.push(dashboardPath((result.dashboard as Dashboard).slug))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -44,7 +45,6 @@ export default function CreateDashboard() {
|
||||||
<div className="mx-auto w-full max-w-2xl">
|
<div className="mx-auto w-full max-w-2xl">
|
||||||
<div className="rounded-lg px-6 py-4 sm:py-0">
|
<div className="rounded-lg px-6 py-4 sm:py-0">
|
||||||
<Title className="!mt-0" text="Create a dashboard" />
|
<Title className="!mt-0" text="Create a dashboard" />
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<div className="form-control w-full">
|
<div className="form-control w-full">
|
||||||
<label className="label">
|
<label className="label">
|
||||||
|
@ -56,7 +56,7 @@ export default function CreateDashboard() {
|
||||||
placeholder="e.g. Elon Mania Dashboard"
|
placeholder="e.g. Elon Mania Dashboard"
|
||||||
className="input input-bordered resize-none"
|
className="input input-bordered resize-none"
|
||||||
autoFocus
|
autoFocus
|
||||||
maxLength={100}
|
maxLength={MAX_DASHBOARD_NAME_LENGTH}
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value || '')}
|
onChange={(e) => setName(e.target.value || '')}
|
||||||
/>
|
/>
|
||||||
|
@ -75,7 +75,7 @@ export default function CreateDashboard() {
|
||||||
'btn btn-primary normal-case',
|
'btn btn-primary normal-case',
|
||||||
isSubmitting && 'loading disabled'
|
isSubmitting && 'loading disabled'
|
||||||
)}
|
)}
|
||||||
disabled={isSubmitting || upload.isLoading}
|
disabled={isSubmitting || !isValid || upload.isLoading}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
await saveDashboard(name)
|
await saveDashboard(name)
|
||||||
|
@ -84,9 +84,9 @@ export default function CreateDashboard() {
|
||||||
>
|
>
|
||||||
{isSubmitting ? 'Creating...' : 'Create a dashboard'}
|
{isSubmitting ? 'Creating...' : 'Create a dashboard'}
|
||||||
</button>
|
</button>
|
||||||
|
{error !== '' && <div className="text-red-700">{error}</div>}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<Spacer h={6} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
@ -13,10 +13,10 @@ import clsx from 'clsx'
|
||||||
import { Button } from 'web/components/button'
|
import { Button } from 'web/components/button'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { ShareDashboardModal } from 'web/components/share-dashboard-modal'
|
import { ShareDashboardModal } from 'web/components/share-dashboard-modal'
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { Row } from 'web/components/layout/row'
|
import { Row } from 'web/components/layout/row'
|
||||||
import { Col } from 'web/components/layout/col'
|
import { Col } from 'web/components/layout/col'
|
||||||
import { ENV_CONFIG } from 'common/envs/constants'
|
import { ENV_CONFIG } from 'common/envs/constants'
|
||||||
|
import Custom404 from 'web/pages/404'
|
||||||
|
|
||||||
export const getStaticProps = fromPropz(getStaticPropz)
|
export const getStaticProps = fromPropz(getStaticPropz)
|
||||||
export async function getStaticPropz(props: { params: { slugs: string[] } }) {
|
export async function getStaticPropz(props: { params: { slugs: string[] } }) {
|
||||||
|
@ -47,20 +47,24 @@ export default function DashboardPage(props: {
|
||||||
props = usePropz(props, getStaticPropz) ?? {
|
props = usePropz(props, getStaticPropz) ?? {
|
||||||
dashboard: null,
|
dashboard: null,
|
||||||
}
|
}
|
||||||
|
const [isShareOpen, setShareOpen] = useState(false)
|
||||||
|
|
||||||
|
if (props.dashboard === null) {
|
||||||
|
return <Custom404 />
|
||||||
|
}
|
||||||
|
|
||||||
const shareUrl = `https://${ENV_CONFIG.domain}${dashboardPath(
|
const shareUrl = `https://${ENV_CONFIG.domain}${dashboardPath(
|
||||||
props?.dashboard.slug
|
props?.dashboard.slug
|
||||||
)}`
|
)}`
|
||||||
const [isShareOpen, setShareOpen] = useState(false)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<div className="mx-auto w-full max-w-3xl ">
|
<div className="mx-auto w-full max-w-3xl ">
|
||||||
<Spacer h={1} />
|
<Spacer h={1} />
|
||||||
<Title className="!mt-0" text={props.dashboard?.name ?? ''} />
|
<Title className="!mt-0" text={props.dashboard.name} />
|
||||||
<Row>
|
<Row>
|
||||||
<Col className=" flex-1">
|
<Col className="flex-1">
|
||||||
<div className={'items-right inline-flex'}>
|
<div className={'inline-flex'}>
|
||||||
<div className="mr-1 text-gray-500">Created by</div>
|
<div className="mr-1 text-gray-500">Created by</div>
|
||||||
<UserLink
|
<UserLink
|
||||||
className="text-neutral"
|
className="text-neutral"
|
||||||
|
@ -91,14 +95,11 @@ export default function DashboardPage(props: {
|
||||||
</Button>
|
</Button>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Spacer h={1} />
|
|
||||||
|
|
||||||
<Spacer h={1} />
|
<Spacer h={2} />
|
||||||
<div className="rounded-lg bg-white px-6 py-4 sm:py-0">
|
<div className="rounded-lg bg-white px-6 py-4 sm:py-0">
|
||||||
<div className="form-control w-full">
|
<div className="form-control w-full py-2">
|
||||||
<Spacer h={6} />
|
<Content content={props.dashboard.content} />
|
||||||
<Content content={props.dashboard?.content ?? ''} />
|
|
||||||
<Spacer h={6} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user