@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
// A workspace: its projects, and a form to create another (spec §3.1). The projects are listed
|
||||
// through `tenancy.project.list`, which reads them inside the workspace's own scope -- a workspace of
|
||||
// another organization, or one the person has no place in, is the not-found page.
|
||||
|
||||
import { moduleSelected } from "@app/modules/inclusion"
|
||||
import { GuidesSetupCard } from "@conusai-kit/guides/panel" // kit:guides
|
||||
import { FormPanel, Page as PageFrame, PageHeader, PageSection, ResourceList } from "@conusai-kit/ui/patterns"
|
||||
import { createFileRoute } from "@tanstack/react-router"
|
||||
import { createServerFn } from "@tanstack/react-start"
|
||||
import type { ReactElement } from "react"
|
||||
import type { WorkspaceHomeData, WorkspaceParams } from "../server/org-pages"
|
||||
import { useFrameRouter } from "../ui/frame-router"
|
||||
import { ProcedureForm } from "../ui/procedure-form"
|
||||
import { projectHref } from "../ui/projects"
|
||||
|
||||
const ROUTE = "/$org/$workspace/"
|
||||
|
||||
const read = createServerFn({ method: "GET" })
|
||||
.validator((params: WorkspaceParams) => params)
|
||||
.handler(async ({ data }): Promise<WorkspaceHomeData> => {
|
||||
const [{ reported }, { workspaceHomeData }] = await Promise.all([
|
||||
import("../server/page"),
|
||||
import("../server/org-pages"),
|
||||
])
|
||||
return reported(ROUTE, () => workspaceHomeData(data))
|
||||
})
|
||||
|
||||
export const Route = createFileRoute("/$org/$workspace/")({
|
||||
loader: ({ params }) => read({ data: { org: params.org, workspace: params.workspace } }),
|
||||
head: ({ loaderData }) => ({ meta: loaderData ? [{ title: loaderData.title }] : [] }),
|
||||
component: Page,
|
||||
})
|
||||
|
||||
function Page(): ReactElement {
|
||||
const { org, workspace } = Route.useParams()
|
||||
const data = Route.useLoaderData()
|
||||
const create = data.create
|
||||
const { navigate } = useFrameRouter()
|
||||
return (
|
||||
<PageFrame>
|
||||
<PageHeader
|
||||
title={data.title}
|
||||
description={data.description}
|
||||
actions={
|
||||
create ? (
|
||||
<FormPanel label={create.title}>
|
||||
{(complete) => (
|
||||
<ProcedureForm
|
||||
procedure="tenancy.project.create"
|
||||
onComplete={complete}
|
||||
hidden={{ org, workspace }}
|
||||
submitLabel={create.submit}
|
||||
fields={create.fields}
|
||||
/>
|
||||
)}
|
||||
</FormPanel>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
{/* kit:guides:begin */}
|
||||
{moduleSelected("guides") && <GuidesSetupCard locale={data.locale} scope={{ org, workspace }} />}
|
||||
{/* kit:guides:end */}
|
||||
<PageSection title={data.projectsHeading}>
|
||||
<ResourceList
|
||||
label={data.projectsHeading}
|
||||
columns={[
|
||||
{ id: "name", header: data.columnName, wrap: true },
|
||||
{ id: "moduleKey", header: data.columnModule },
|
||||
]}
|
||||
data={data.projects}
|
||||
rowId={(project) => project.slug}
|
||||
rowHref={(project) => projectHref(org, workspace, project.slug)}
|
||||
navigate={navigate}
|
||||
rowLabel={(project) => project.name}
|
||||
empty={{ title: data.none }}
|
||||
/>
|
||||
</PageSection>
|
||||
</PageFrame>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user