Skip to content

Commit e62677e

Browse files
authored
feat: add audit page title, subtitle, and CLI snippet (coder#3419)
* resolves coder#3356 * scaffolded out new audit page header resolves coder#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)