mirror of https://github.com/coder/coder.git
feat: add feedback link to footer (#2447)
* add ability to activate users resolves #2254 * added test * PR feedback * guarding against null validation_contains field * fixing type for ParameterSchema resolves #2161 * added report link to footer resolves #1885 * added test * Footer story * fix broken test
This commit is contained in:
parent
64b92eea67
commit
7dcfea10dc
|
@ -0,0 +1,9 @@
|
|||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
<!--- Tell us what should happen -->
|
||||
|
||||
## Current Behavior
|
||||
|
||||
<!--- Tell us what happens instead of the expected behavior -->
|
|
@ -1,4 +1,7 @@
|
|||
import { FC } from "react"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { useActor } from "@xstate/react"
|
||||
import { FC, useContext } from "react"
|
||||
import { XServiceContext } from "../../xServices/StateContext"
|
||||
import { Footer } from "../Footer/Footer"
|
||||
import { Navbar } from "../Navbar/Navbar"
|
||||
import { RequireAuth } from "../RequireAuth/RequireAuth"
|
||||
|
@ -10,12 +13,30 @@ interface AuthAndFrameProps {
|
|||
/**
|
||||
* Wraps page in RequireAuth and renders it between Navbar and Footer
|
||||
*/
|
||||
export const AuthAndFrame: FC<AuthAndFrameProps> = ({ children }) => (
|
||||
<RequireAuth>
|
||||
<>
|
||||
<Navbar />
|
||||
{children}
|
||||
<Footer />
|
||||
</>
|
||||
</RequireAuth>
|
||||
)
|
||||
export const AuthAndFrame: FC<AuthAndFrameProps> = ({ children }) => {
|
||||
const styles = useStyles()
|
||||
const xServices = useContext(XServiceContext)
|
||||
|
||||
const [buildInfoState] = useActor(xServices.buildInfoXService)
|
||||
|
||||
return (
|
||||
<RequireAuth>
|
||||
<div className={styles.site}>
|
||||
<Navbar />
|
||||
<div className={styles.siteContent}>{children}</div>
|
||||
<Footer buildInfo={buildInfoState.context.buildInfo} />
|
||||
</div>
|
||||
</RequireAuth>
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
site: {
|
||||
display: "flex",
|
||||
minHeight: "100vh",
|
||||
flexDirection: "column",
|
||||
},
|
||||
siteContent: {
|
||||
flex: 1,
|
||||
},
|
||||
}))
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { Story } from "@storybook/react"
|
||||
import { Footer, FooterProps } from "./Footer"
|
||||
|
||||
export default {
|
||||
title: "components/Footer",
|
||||
component: Footer,
|
||||
}
|
||||
|
||||
const Template: Story<FooterProps> = (args) => <Footer {...args} />
|
||||
|
||||
export const Example = Template.bind({})
|
||||
Example.args = {
|
||||
buildInfo: {
|
||||
external_url: "",
|
||||
version: "test-1.2.3",
|
||||
},
|
||||
}
|
|
@ -5,10 +5,18 @@ import { Footer, Language } from "./Footer"
|
|||
describe("Footer", () => {
|
||||
it("renders content", async () => {
|
||||
// When
|
||||
render(<Footer />)
|
||||
render(<Footer buildInfo={MockBuildInfo} />)
|
||||
|
||||
// Then
|
||||
await screen.findByText("Copyright", { exact: false })
|
||||
await screen.findByText(Language.buildInfoText(MockBuildInfo))
|
||||
const reportBugLink = screen.getByText(Language.reportBugLink, { exact: false }).closest("a")
|
||||
if (!reportBugLink) {
|
||||
throw new Error("Bug report link not found in footer")
|
||||
}
|
||||
|
||||
expect(reportBugLink.getAttribute("href")).toBe(
|
||||
`https://github.com/coder/coder/issues/new?labels=bug,needs+grooming&title=Bug+in+${MockBuildInfo.version}:&template=external_bug_report.md`,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,39 +1,34 @@
|
|||
import Link from "@material-ui/core/Link"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import { useActor } from "@xstate/react"
|
||||
import React, { useContext } from "react"
|
||||
import * as TypesGen from "../../api/typesGenerated"
|
||||
import { XServiceContext } from "../../xServices/StateContext"
|
||||
|
||||
export const Language = {
|
||||
buildInfoText: (buildInfo: TypesGen.BuildInfoResponse): string => {
|
||||
return `Coder ${buildInfo.version}`
|
||||
},
|
||||
copyrightText: `Copyright \u00a9 ${new Date().getFullYear()} Coder Technologies, Inc. All rights reserved.`,
|
||||
reportBugLink: "Report an issue",
|
||||
}
|
||||
|
||||
export const Footer: React.FC = ({ children }) => {
|
||||
export interface FooterProps {
|
||||
buildInfo?: TypesGen.BuildInfoResponse
|
||||
}
|
||||
|
||||
export const Footer: React.FC<FooterProps> = ({ buildInfo }) => {
|
||||
const styles = useFooterStyles()
|
||||
const xServices = useContext(XServiceContext)
|
||||
const [buildInfoState] = useActor(xServices.buildInfoXService)
|
||||
|
||||
const githubUrl = `https://github.com/coder/coder/issues/new?labels=bug,needs+grooming&title=Bug+in+${buildInfo?.version}:&template=external_bug_report.md`
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
{children}
|
||||
<div className={styles.copyRight}>
|
||||
<Typography color="textSecondary" variant="caption">
|
||||
{`Copyright \u00a9 ${new Date().getFullYear()} Coder Technologies, Inc. All rights reserved.`}
|
||||
</Typography>
|
||||
</div>
|
||||
{buildInfoState.context.buildInfo && (
|
||||
<Link className={styles.link} variant="caption" target="_blank" href={githubUrl}>
|
||||
🪲 {Language.reportBugLink}
|
||||
</Link>
|
||||
<div className={styles.copyRight}>{Language.copyrightText}</div>
|
||||
{buildInfo && (
|
||||
<div className={styles.buildInfo}>
|
||||
<Link
|
||||
className={styles.link}
|
||||
variant="caption"
|
||||
target="_blank"
|
||||
href={buildInfoState.context.buildInfo.external_url}
|
||||
>
|
||||
{Language.buildInfoText(buildInfoState.context.buildInfo)}
|
||||
<Link className={styles.link} variant="caption" target="_blank" href={buildInfo.external_url}>
|
||||
{Language.buildInfoText(buildInfo)}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
|
Loading…
Reference in New Issue