82 lines
3.1 KiB
TypeScript
82 lines
3.1 KiB
TypeScript
// 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>
|
|
)
|
|
}
|