56 lines
2.0 KiB
TypeScript
56 lines
2.0 KiB
TypeScript
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
|
// The organization's workspaces and the projects of each (spec §3.1).
|
|
|
|
import { projectList, workspaceList } from "@conusai-kit/tenancy"
|
|
import type { ReactElement } from "react"
|
|
import { orFallback } from "../../src/server/guard"
|
|
import { pageContext } from "../../src/server/page"
|
|
import { PROJECT_ENTRIES, projectHref } from "../../src/ui/projects"
|
|
|
|
export const dynamic = "force-dynamic"
|
|
|
|
export default async function OrgHome({ params }: { params: Promise<{ org: string }> }): Promise<ReactElement> {
|
|
const { org } = await params
|
|
const { caller, i18n, path } = await pageContext()
|
|
const projects = await orFallback(path, async () => {
|
|
const { workspaces } = await caller.call(workspaceList, { org })
|
|
return Promise.all(
|
|
workspaces.map(async (workspace) => ({
|
|
workspace,
|
|
projects: (await caller.call(projectList, { org, workspace: workspace.slug })).projects,
|
|
})),
|
|
)
|
|
})
|
|
|
|
return (
|
|
<>
|
|
<h1>{i18n.message("app.workspaces")}</h1>
|
|
<p>
|
|
<a href={`/${org}/workspaces`}>{i18n.message("workspace.create")}</a>
|
|
</p>
|
|
{projects.length === 0 ? <p>{i18n.message("workspace.none")}</p> : null}
|
|
{projects.map(({ workspace, projects: inWorkspace }) => (
|
|
<section key={workspace.slug}>
|
|
<h2>
|
|
<a href={`/${org}/${workspace.slug}`}>{workspace.name}</a>
|
|
</h2>
|
|
<p>{i18n.message("workspace.projectCount", { count: inWorkspace.length })}</p>
|
|
<ul>
|
|
{inWorkspace.map((project) => (
|
|
<li key={project.slug}>
|
|
<a href={projectHref(org, workspace.slug, project.slug)}>{project.name}</a>:
|
|
{PROJECT_ENTRIES.map((entry) => (
|
|
<span key={entry.href}>
|
|
{" "}
|
|
<a href={projectHref(org, workspace.slug, project.slug, entry)}>{i18n.message(entry.label)}</a>
|
|
</span>
|
|
))}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
))}
|
|
</>
|
|
)
|
|
}
|