Skip to content

Commit e62677e

Browse files
authored
feat: add audit page title, subtitle, and CLI snippet (#3419)
* resolves #3356 * scaffolded out new audit page header resolves #3357 * added tests and stories * run prettier
1 parent 049e7cb commit e62677e

File tree

10 files changed

+163
-16
lines changed

10 files changed

+163
-16
lines changed

site/src/components/CodeExample/CodeExample.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,28 @@ export interface CodeExampleProps {
88
code: string
99
className?: string
1010
buttonClassName?: string
11+
tooltipTitle?: string
1112
}
1213

1314
/**
1415
* Component to show single-line code examples, with a copy button
1516
*/
16-
export const CodeExample: FC<CodeExampleProps> = ({ code, className, buttonClassName }) => {
17+
export const CodeExample: FC<CodeExampleProps> = ({
18+
code,
19+
className,
20+
buttonClassName,
21+
tooltipTitle,
22+
}) => {
1723
const styles = useStyles()
1824

1925
return (
2026
<div className={combineClasses([styles.root, className])}>
2127
<code className={styles.code}>{code}</code>
22-
<CopyButton text={code} buttonClassName={combineClasses([styles.button, buttonClassName])} />
28+
<CopyButton
29+
text={code}
30+
tooltipTitle={tooltipTitle}
31+
buttonClassName={combineClasses([styles.button, buttonClassName])}
32+
/>
2333
</div>
2434
)
2535
}

site/src/components/CopyButton/CopyButton.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ interface CopyButtonProps {
1111
ctaCopy?: string
1212
wrapperClassName?: string
1313
buttonClassName?: string
14+
tooltipTitle?: string
15+
}
16+
17+
export const Language = {
18+
tooltipTitle: "Copy to clipboard",
19+
ariaLabel: "Copy to clipboard",
1420
}
1521

1622
/**
@@ -21,6 +27,7 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
2127
ctaCopy,
2228
wrapperClassName = "",
2329
buttonClassName = "",
30+
tooltipTitle = Language.tooltipTitle,
2431
}) => {
2532
const styles = useStyles()
2633
const [isCopied, setIsCopied] = useState<boolean>(false)
@@ -56,12 +63,13 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
5663
}
5764

5865
return (
59-
<Tooltip title="Copy to Clipboard" placement="top">
66+
<Tooltip title={tooltipTitle} placement="top">
6067
<div className={combineClasses([styles.copyButtonWrapper, wrapperClassName])}>
6168
<IconButton
6269
className={combineClasses([styles.copyButton, buttonClassName])}
6370
onClick={copyToClipboard}
6471
size="small"
72+
aria-label={Language.ariaLabel}
6573
>
6674
{isCopied ? (
6775
<Check className={styles.fileCopyIcon} />

site/src/components/Stack/Stack.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,39 @@ import { combineClasses } from "../../util/combineClasses"
55

66
type Direction = "column" | "row"
77

8-
interface StyleProps {
9-
direction: Direction
10-
spacing: number
8+
export interface StackProps {
9+
className?: string
10+
direction?: Direction
11+
spacing?: number
1112
alignItems?: CSSProperties["alignItems"]
13+
justifyContent?: CSSProperties["justifyContent"]
1214
}
1315

16+
type StyleProps = Omit<StackProps, "className">
17+
1418
const useStyles = makeStyles((theme) => ({
1519
stack: {
1620
display: "flex",
1721
flexDirection: ({ direction }: StyleProps) => direction,
18-
gap: ({ spacing }: StyleProps) => theme.spacing(spacing),
22+
gap: ({ spacing }: StyleProps) => spacing && theme.spacing(spacing),
1923
alignItems: ({ alignItems }: StyleProps) => alignItems,
24+
justifyContent: ({ justifyContent }: StyleProps) => justifyContent,
2025

2126
[theme.breakpoints.down("sm")]: {
2227
width: "100%",
2328
},
2429
},
2530
}))
2631

27-
export interface StackProps {
28-
className?: string
29-
direction?: Direction
30-
spacing?: number
31-
alignItems?: CSSProperties["alignItems"]
32-
}
33-
3432
export const Stack: FC<StackProps> = ({
3533
children,
3634
className,
3735
direction = "column",
3836
spacing = 2,
3937
alignItems,
38+
justifyContent,
4039
}) => {
41-
const styles = useStyles({ spacing, direction, alignItems })
40+
const styles = useStyles({ spacing, direction, alignItems, justifyContent })
4241

4342
return <div className={combineClasses([styles.stack, className])}>{children}</div>
4443
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { FC } from "react"
2+
import { HelpTooltip, HelpTooltipText, HelpTooltipTitle } from "./HelpTooltip"
3+
4+
export const Language = {
5+
title: "What is an audit log?",
6+
body: "An audit log is a record of events and changes made throughout a system.",
7+
}
8+
9+
export const AuditHelpTooltip: FC = () => {
10+
return (
11+
<HelpTooltip>
12+
<HelpTooltipTitle>{Language.title}</HelpTooltipTitle>
13+
<HelpTooltipText>{Language.body}</HelpTooltipText>
14+
</HelpTooltip>
15+
)
16+
}

site/src/components/Tooltips/HelpTooltip/HelpTooltip.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ export interface HelpTooltipProps {
1515
size?: Size
1616
}
1717

18+
export const Language = {
19+
ariaLabel: "tooltip",
20+
}
21+
1822
const HelpTooltipContext = createContext<{ open: boolean; onClose: () => void } | undefined>(
1923
undefined,
2024
)
@@ -52,6 +56,7 @@ export const HelpTooltip: React.FC<HelpTooltipProps> = ({ children, open, size =
5256
onMouseEnter={() => {
5357
setIsOpen(true)
5458
}}
59+
aria-label={Language.ariaLabel}
5560
>
5661
<HelpIcon className={styles.icon} />
5762
</button>

site/src/components/Tooltips/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export { AgentHelpTooltip } from "./AgentHelpTooltip"
2+
export { AuditHelpTooltip } from "./AuditHelpTooltip"
23
export { OutdatedHelpTooltip } from "./OutdatedHelpTooltip"
34
export { ResourcesHelpTooltip } from "./ResourcesHelpTooltip"
45
export { WorkspaceHelpTooltip } from "./WorkspaceHelpTooltip"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { fireEvent, screen } from "@testing-library/react"
2+
import { Language as CopyButtonLanguage } from "components/CopyButton/CopyButton"
3+
import { Language as AuditTooltipLanguage } from "components/Tooltips/AuditHelpTooltip"
4+
import { Language as TooltipLanguage } from "components/Tooltips/HelpTooltip/HelpTooltip"
5+
import { render } from "testHelpers/renderHelpers"
6+
import AuditPage from "./AuditPage"
7+
import { Language as AuditViewLanguage } from "./AuditPageView"
8+
9+
describe("AuditPage", () => {
10+
it("renders a page with a title and subtitle", async () => {
11+
// When
12+
render(<AuditPage />)
13+
14+
// Then
15+
await screen.findByText(AuditViewLanguage.title)
16+
await screen.findByText(AuditViewLanguage.subtitle)
17+
const tooltipIcon = await screen.findByRole("button", { name: TooltipLanguage.ariaLabel })
18+
fireEvent.mouseOver(tooltipIcon)
19+
expect(await screen.findByText(AuditTooltipLanguage.title)).toBeInTheDocument()
20+
})
21+
22+
it("describes the CLI command", async () => {
23+
// When
24+
render(<AuditPage />)
25+
26+
// Then
27+
await screen.findByText("coder audit [organization_ID]") // CLI command; untranslated
28+
const copyIcon = await screen.findByRole("button", { name: CopyButtonLanguage.ariaLabel })
29+
fireEvent.mouseOver(copyIcon)
30+
expect(await screen.findByText(AuditViewLanguage.tooltipTitle)).toBeInTheDocument()
31+
})
32+
})
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { FC } from "react"
2+
import { AuditPageView } from "./AuditPageView"
23

34
// REMARK: This page is in-progress and hidden from users
45
const AuditPage: FC = () => {
5-
return <div>Audit</div>
6+
return <AuditPageView />
67
}
78

89
export default AuditPage
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ComponentMeta, Story } from "@storybook/react"
2+
import { AuditPageView } from "./AuditPageView"
3+
4+
export default {
5+
title: "pages/AuditPageView",
6+
component: AuditPageView,
7+
} as ComponentMeta<typeof AuditPageView>
8+
9+
const Template: Story = (args) => <AuditPageView {...args} />
10+
11+
export const AuditPage = Template.bind({})
12+
13+
export const AuditPageSmallViewport = Template.bind({})
14+
AuditPageSmallViewport.parameters = {
15+
chromatic: { viewports: [600] },
16+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { makeStyles } from "@material-ui/core/styles"
2+
import { CodeExample } from "components/CodeExample/CodeExample"
3+
import { Margins } from "components/Margins/Margins"
4+
import { PageHeader, PageHeaderSubtitle, PageHeaderTitle } from "components/PageHeader/PageHeader"
5+
import { Stack } from "components/Stack/Stack"
6+
import { AuditHelpTooltip } from "components/Tooltips"
7+
import { FC } from "react"
8+
9+
export const Language = {
10+
title: "Audit",
11+
subtitle: "View events in your audit log.",
12+
tooltipTitle: "Copy to clipboard and try the Coder CLI",
13+
}
14+
15+
export const AuditPageView: FC = () => {
16+
const styles = useStyles()
17+
18+
return (
19+
<Margins>
20+
<Stack justifyContent="space-between" className={styles.headingContainer}>
21+
<PageHeader className={styles.headingStyles}>
22+
<PageHeaderTitle>
23+
<Stack direction="row" spacing={1} alignItems="center">
24+
<span>{Language.title}</span>
25+
<AuditHelpTooltip />
26+
</Stack>
27+
</PageHeaderTitle>
28+
<PageHeaderSubtitle>{Language.subtitle}</PageHeaderSubtitle>
29+
</PageHeader>
30+
<CodeExample
31+
className={styles.codeExampleStyles}
32+
tooltipTitle={Language.tooltipTitle}
33+
code="coder audit [organization_ID]"
34+
/>
35+
</Stack>
36+
</Margins>
37+
)
38+
}
39+
40+
const useStyles = makeStyles((theme) => ({
41+
headingContainer: {
42+
marginTop: theme.spacing(6),
43+
marginBottom: theme.spacing(5),
44+
flexDirection: "row",
45+
alignItems: "center",
46+
47+
[theme.breakpoints.down("sm")]: {
48+
flexDirection: "column",
49+
alignItems: "start",
50+
},
51+
},
52+
headingStyles: {
53+
paddingTop: "0px",
54+
paddingBottom: "0px",
55+
},
56+
codeExampleStyles: {
57+
height: "fit-content",
58+
},
59+
}))

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