diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index ce88dfc6c6e32..d979a37f4d616 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -132,9 +132,15 @@ const WorkspaceSettingsPage = lazy( const CreateTokenPage = lazy( () => import("./pages/CreateTokenPage/CreateTokenPage"), ) + +const TemplateDocsPage = lazy( + () => import("./pages/TemplatePage/TemplateDocsPage/TemplateDocsPage"), +) + const TemplateFilesPage = lazy( () => import("./pages/TemplatePage/TemplateFilesPage/TemplateFilesPage"), ) + const TemplateVersionsPage = lazy( () => import("./pages/TemplatePage/TemplateVersionsPage/TemplateVersionsPage"), @@ -174,6 +180,7 @@ export const AppRouter: FC = () => { }> } /> + } /> } /> } /> diff --git a/site/src/components/TemplateLayout/TemplateLayout.tsx b/site/src/components/TemplateLayout/TemplateLayout.tsx index f9b91da40556d..2dfd1569110a3 100644 --- a/site/src/components/TemplateLayout/TemplateLayout.tsx +++ b/site/src/components/TemplateLayout/TemplateLayout.tsx @@ -110,6 +110,18 @@ export const TemplateLayout: FC<{ children?: JSX.Element }> = ({ > Summary + + combineClasses([ + styles.tabItem, + isActive ? styles.tabItemActive : undefined, + ]) + } + > + Docs + {data.permissions.canUpdateTemplate && ( jest.fn()) + +const TEMPLATE_NAME = "coder-ts" + +Object.defineProperty(window, "ResizeObserver", { + value: ResizeObserver, +}) + +const renderPage = () => + renderWithAuth( + + + , + { + route: `/templates/${TEMPLATE_NAME}/docs`, + path: "/templates/:template/docs", + }, + ) + +describe("TemplateSummaryPage", () => { + it("shows the template readme", async () => { + renderPage() + await screen.findByTestId("markdown") + }) +}) diff --git a/site/src/pages/TemplatePage/TemplateDocsPage/TemplateDocsPage.tsx b/site/src/pages/TemplatePage/TemplateDocsPage/TemplateDocsPage.tsx new file mode 100644 index 0000000000000..d5e3670dcc4a0 --- /dev/null +++ b/site/src/pages/TemplatePage/TemplateDocsPage/TemplateDocsPage.tsx @@ -0,0 +1,51 @@ +import { makeStyles } from "@material-ui/core/styles" +import { MemoizedMarkdown } from "components/Markdown/Markdown" +import { useTemplateLayoutContext } from "components/TemplateLayout/TemplateLayout" +import frontMatter from "front-matter" +import { Helmet } from "react-helmet-async" +import { pageTitle } from "util/page" + +export default function TemplateDocsPage() { + const { template, activeVersion } = useTemplateLayoutContext() + const styles = useStyles() + + const readme = frontMatter(activeVersion.readme) + + return ( + <> + + {pageTitle(`${template.name} ยท Documentation`)} + + +
+
README.md
+
+ {readme.body} +
+
+ + ) +} + +export const useStyles = makeStyles((theme) => { + return { + markdownSection: { + background: theme.palette.background.paper, + border: `1px solid ${theme.palette.divider}`, + borderRadius: theme.shape.borderRadius, + }, + + readmeLabel: { + color: theme.palette.text.secondary, + fontWeight: 600, + padding: theme.spacing(2, 3), + borderBottom: `1px solid ${theme.palette.divider}`, + }, + + markdownWrapper: { + padding: theme.spacing(0, 3, 5), + maxWidth: 800, + margin: "auto", + }, + } +}) diff --git a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPage.test.tsx b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPage.test.tsx index 7580f663bf3f9..05bacaa8fa5fd 100644 --- a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPage.test.tsx +++ b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPage.test.tsx @@ -4,7 +4,6 @@ import { rest } from "msw" import { ResizeObserver } from "resize-observer" import { MockTemplate, - MockWorkspaceResource, MockTemplateVersion, MockMemberPermissions, } from "testHelpers/entities" @@ -31,15 +30,13 @@ const renderPage = () => ) describe("TemplateSummaryPage", () => { - it("shows the template name, readme and resources", async () => { + it("shows the template name and resources", async () => { // Mocking the dayjs module within the createDayString file const mock = jest.spyOn(CreateDayString, "createDayString") mock.mockImplementation(() => "a minute ago") renderPage() await screen.findByText(MockTemplate.display_name) - await screen.findByTestId("markdown") - screen.getByText(MockWorkspaceResource.name) screen.queryAllByText(`${MockTemplateVersion.name}`).length }) it("does not allow a member to delete a template", () => { diff --git a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx index 803692804ed60..47babcc06ade8 100644 --- a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx +++ b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx @@ -5,14 +5,13 @@ import { WorkspaceResource, } from "api/typesGenerated" import { Loader } from "components/Loader/Loader" -import { MemoizedMarkdown } from "components/Markdown/Markdown" import { Stack } from "components/Stack/Stack" import { TemplateResourcesTable } from "components/TemplateResourcesTable/TemplateResourcesTable" import { TemplateStats } from "components/TemplateStats/TemplateStats" -import frontMatter from "front-matter" -import { FC } from "react" +import { FC, useEffect } from "react" import { DAUChart } from "../../../components/DAUChart/DAUChart" import { TemplateSummaryData } from "./data" +import { useLocation, useNavigate } from "react-router-dom" export interface TemplateSummaryPageViewProps { data?: TemplateSummaryData @@ -25,14 +24,22 @@ export const TemplateSummaryPageView: FC = ({ template, activeVersion, }) => { - const styles = useStyles() + const navigate = useNavigate() + const location = useLocation() + + useEffect(() => { + if (location.hash === "#readme") { + // We moved the readme to the docs page, but we known that some users + // have bookmarked the readme or linked it elsewhere. Redirect them to the docs page. + navigate(`/templates/${template.name}/docs`, { replace: true }) + } + }, [template, navigate, location]) if (!data) { return } const { daus, resources } = data - const readme = frontMatter(activeVersion.readme) const getStartedResources = (resources: WorkspaceResource[]) => { return resources.filter( @@ -45,13 +52,6 @@ export const TemplateSummaryPageView: FC = ({ {daus && } - -
-
README.md
-
- {readme.body} -
-
) }