Skip to content

Commit 7dcfea1

Browse files
authored
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
1 parent 64b92ee commit 7dcfea1

File tree

5 files changed

+82
-32
lines changed

5 files changed

+82
-32
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!--- Provide a general summary of the issue in the Title above -->
2+
3+
## Expected Behavior
4+
5+
<!--- Tell us what should happen -->
6+
7+
## Current Behavior
8+
9+
<!--- Tell us what happens instead of the expected behavior -->
Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { FC } from "react"
1+
import { makeStyles } from "@material-ui/core/styles"
2+
import { useActor } from "@xstate/react"
3+
import { FC, useContext } from "react"
4+
import { XServiceContext } from "../../xServices/StateContext"
25
import { Footer } from "../Footer/Footer"
36
import { Navbar } from "../Navbar/Navbar"
47
import { RequireAuth } from "../RequireAuth/RequireAuth"
@@ -10,12 +13,30 @@ interface AuthAndFrameProps {
1013
/**
1114
* Wraps page in RequireAuth and renders it between Navbar and Footer
1215
*/
13-
export const AuthAndFrame: FC<AuthAndFrameProps> = ({ children }) => (
14-
<RequireAuth>
15-
<>
16-
<Navbar />
17-
{children}
18-
<Footer />
19-
</>
20-
</RequireAuth>
21-
)
16+
export const AuthAndFrame: FC<AuthAndFrameProps> = ({ children }) => {
17+
const styles = useStyles()
18+
const xServices = useContext(XServiceContext)
19+
20+
const [buildInfoState] = useActor(xServices.buildInfoXService)
21+
22+
return (
23+
<RequireAuth>
24+
<div className={styles.site}>
25+
<Navbar />
26+
<div className={styles.siteContent}>{children}</div>
27+
<Footer buildInfo={buildInfoState.context.buildInfo} />
28+
</div>
29+
</RequireAuth>
30+
)
31+
}
32+
33+
const useStyles = makeStyles(() => ({
34+
site: {
35+
display: "flex",
36+
minHeight: "100vh",
37+
flexDirection: "column",
38+
},
39+
siteContent: {
40+
flex: 1,
41+
},
42+
}))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Story } from "@storybook/react"
2+
import { Footer, FooterProps } from "./Footer"
3+
4+
export default {
5+
title: "components/Footer",
6+
component: Footer,
7+
}
8+
9+
const Template: Story<FooterProps> = (args) => <Footer {...args} />
10+
11+
export const Example = Template.bind({})
12+
Example.args = {
13+
buildInfo: {
14+
external_url: "",
15+
version: "test-1.2.3",
16+
},
17+
}

site/src/components/Footer/Footer.test.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ import { Footer, Language } from "./Footer"
55
describe("Footer", () => {
66
it("renders content", async () => {
77
// When
8-
render(<Footer />)
8+
render(<Footer buildInfo={MockBuildInfo} />)
99

1010
// Then
1111
await screen.findByText("Copyright", { exact: false })
1212
await screen.findByText(Language.buildInfoText(MockBuildInfo))
13+
const reportBugLink = screen.getByText(Language.reportBugLink, { exact: false }).closest("a")
14+
if (!reportBugLink) {
15+
throw new Error("Bug report link not found in footer")
16+
}
17+
18+
expect(reportBugLink.getAttribute("href")).toBe(
19+
`https://github.com/coder/coder/issues/new?labels=bug,needs+grooming&title=Bug+in+${MockBuildInfo.version}:&template=external_bug_report.md`,
20+
)
1321
})
1422
})

site/src/components/Footer/Footer.tsx

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,34 @@
11
import Link from "@material-ui/core/Link"
22
import { makeStyles } from "@material-ui/core/styles"
3-
import Typography from "@material-ui/core/Typography"
4-
import { useActor } from "@xstate/react"
5-
import React, { useContext } from "react"
63
import * as TypesGen from "../../api/typesGenerated"
7-
import { XServiceContext } from "../../xServices/StateContext"
84

95
export const Language = {
106
buildInfoText: (buildInfo: TypesGen.BuildInfoResponse): string => {
117
return `Coder ${buildInfo.version}`
128
},
9+
copyrightText: `Copyright \u00a9 ${new Date().getFullYear()} Coder Technologies, Inc. All rights reserved.`,
10+
reportBugLink: "Report an issue",
1311
}
1412

15-
export const Footer: React.FC = ({ children }) => {
13+
export interface FooterProps {
14+
buildInfo?: TypesGen.BuildInfoResponse
15+
}
16+
17+
export const Footer: React.FC<FooterProps> = ({ buildInfo }) => {
1618
const styles = useFooterStyles()
17-
const xServices = useContext(XServiceContext)
18-
const [buildInfoState] = useActor(xServices.buildInfoXService)
19+
20+
const githubUrl = `https://github.com/coder/coder/issues/new?labels=bug,needs+grooming&title=Bug+in+${buildInfo?.version}:&template=external_bug_report.md`
1921

2022
return (
2123
<div className={styles.root}>
22-
{children}
23-
<div className={styles.copyRight}>
24-
<Typography color="textSecondary" variant="caption">
25-
{`Copyright \u00a9 ${new Date().getFullYear()} Coder Technologies, Inc. All rights reserved.`}
26-
</Typography>
27-
</div>
28-
{buildInfoState.context.buildInfo && (
24+
<Link className={styles.link} variant="caption" target="_blank" href={githubUrl}>
25+
&#129714;&nbsp;{Language.reportBugLink}
26+
</Link>
27+
<div className={styles.copyRight}>{Language.copyrightText}</div>
28+
{buildInfo && (
2929
<div className={styles.buildInfo}>
30-
<Link
31-
className={styles.link}
32-
variant="caption"
33-
target="_blank"
34-
href={buildInfoState.context.buildInfo.external_url}
35-
>
36-
{Language.buildInfoText(buildInfoState.context.buildInfo)}
30+
<Link className={styles.link} variant="caption" target="_blank" href={buildInfo.external_url}>
31+
{Language.buildInfoText(buildInfo)}
3732
</Link>
3833
</div>
3934
)}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy