Skip to content

Commit 27e4658

Browse files
committed
Merge branch 'main' of https://github.com/coder/coder into bq/replace-mui-buttons
2 parents 48d65c9 + 3011eca commit 27e4658

File tree

40 files changed

+271
-525
lines changed

40 files changed

+271
-525
lines changed

site/src/api/api.ts

+6-24
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,11 @@ export const watchBuildLogsByTemplateVersionId = (
221221

222222
export const watchWorkspaceAgentLogs = (
223223
agentId: string,
224-
{ after, onMessage, onDone, onError }: WatchWorkspaceAgentLogsOptions,
224+
params?: WatchWorkspaceAgentLogsParams,
225225
) => {
226226
const searchParams = new URLSearchParams({
227227
follow: "true",
228-
after: after.toString(),
228+
after: params?.after?.toString() ?? "",
229229
});
230230

231231
/**
@@ -237,32 +237,14 @@ export const watchWorkspaceAgentLogs = (
237237
searchParams.set("no_compression", "");
238238
}
239239

240-
const socket = createWebSocket(
241-
`/api/v2/workspaceagents/${agentId}/logs`,
240+
return new OneWayWebSocket<TypesGen.WorkspaceAgentLog[]>({
241+
apiRoute: `/api/v2/workspaceagents/${agentId}/logs`,
242242
searchParams,
243-
);
244-
245-
socket.addEventListener("message", (event) => {
246-
const logs = JSON.parse(event.data) as TypesGen.WorkspaceAgentLog[];
247-
onMessage(logs);
248-
});
249-
250-
socket.addEventListener("error", () => {
251-
onError(new Error("socket errored"));
252243
});
253-
254-
socket.addEventListener("close", () => {
255-
onDone?.();
256-
});
257-
258-
return socket;
259244
};
260245

261-
type WatchWorkspaceAgentLogsOptions = {
262-
after: number;
263-
onMessage: (logs: TypesGen.WorkspaceAgentLog[]) => void;
264-
onDone?: () => void;
265-
onError: (error: Error) => void;
246+
type WatchWorkspaceAgentLogsParams = {
247+
after?: number;
266248
};
267249

268250
type WatchBuildLogsByBuildIdOptions = {

site/src/api/queries/workspaces.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {
55
ProvisionerLogLevel,
66
UsageAppName,
77
Workspace,
8+
WorkspaceAgentLog,
89
WorkspaceBuild,
910
WorkspaceBuildParameter,
1011
WorkspacesRequest,
@@ -20,6 +21,7 @@ import type {
2021
QueryClient,
2122
QueryOptions,
2223
UseMutationOptions,
24+
UseQueryOptions,
2325
} from "react-query";
2426
import { checkAuthorization } from "./authCheck";
2527
import { disabledRefetchOptions } from "./util";
@@ -342,20 +344,14 @@ export const buildLogs = (workspace: Workspace) => {
342344
};
343345
};
344346

345-
export const agentLogsKey = (workspaceId: string, agentId: string) => [
346-
"workspaces",
347-
workspaceId,
348-
"agents",
349-
agentId,
350-
"logs",
351-
];
347+
export const agentLogsKey = (agentId: string) => ["agents", agentId, "logs"];
352348

353-
export const agentLogs = (workspaceId: string, agentId: string) => {
349+
export const agentLogs = (agentId: string) => {
354350
return {
355-
queryKey: agentLogsKey(workspaceId, agentId),
351+
queryKey: agentLogsKey(agentId),
356352
queryFn: () => API.getWorkspaceAgentLogs(agentId),
357353
...disabledRefetchOptions,
358-
};
354+
} satisfies UseQueryOptions<WorkspaceAgentLog[]>;
359355
};
360356

361357
// workspace usage options

site/src/components/CodeExample/CodeExample.tsx

+4-30
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Interpolation, Theme } from "@emotion/react";
2-
import { visuallyHidden } from "@mui/utils";
3-
import { type FC, type KeyboardEvent, type MouseEvent, useRef } from "react";
2+
import type { FC } from "react";
43
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
54
import { CopyButton } from "../CopyButton/CopyButton";
65

@@ -21,33 +20,8 @@ export const CodeExample: FC<CodeExampleProps> = ({
2120
// the secure option, not remember to opt in
2221
secret = true,
2322
}) => {
24-
const buttonRef = useRef<HTMLButtonElement>(null);
25-
const triggerButton = (event: KeyboardEvent | MouseEvent) => {
26-
const clickTriggeredOutsideButton =
27-
event.target instanceof HTMLElement &&
28-
!buttonRef.current?.contains(event.target);
29-
30-
if (clickTriggeredOutsideButton) {
31-
buttonRef.current?.click();
32-
}
33-
};
34-
3523
return (
36-
<div
37-
css={styles.container}
38-
className={className}
39-
onClick={triggerButton}
40-
onKeyDown={(event) => {
41-
if (event.key === "Enter") {
42-
triggerButton(event);
43-
}
44-
}}
45-
onKeyUp={(event) => {
46-
if (event.key === " ") {
47-
triggerButton(event);
48-
}
49-
}}
50-
>
24+
<div css={styles.container} className={className}>
5125
<code css={[styles.code, secret && styles.secret]}>
5226
{secret ? (
5327
<>
@@ -60,7 +34,7 @@ export const CodeExample: FC<CodeExampleProps> = ({
6034
* readily available in the HTML itself
6135
*/}
6236
<span aria-hidden>{obfuscateText(code)}</span>
63-
<span css={{ ...visuallyHidden }}>
37+
<span className="sr-only">
6438
Encrypted text. Please access via the copy button.
6539
</span>
6640
</>
@@ -69,7 +43,7 @@ export const CodeExample: FC<CodeExampleProps> = ({
6943
)}
7044
</code>
7145

72-
<CopyButton ref={buttonRef} text={code} />
46+
<CopyButton text={code} label="Copy code" />
7347
</div>
7448
);
7549
};
+35-68
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,44 @@
1-
import { type Interpolation, type Theme, css } from "@emotion/react";
2-
import IconButton from "@mui/material/Button";
3-
import Tooltip from "@mui/material/Tooltip";
1+
import { Button, type ButtonProps } from "components/Button/Button";
2+
import {
3+
Tooltip,
4+
TooltipContent,
5+
TooltipProvider,
6+
TooltipTrigger,
7+
} from "components/Tooltip/Tooltip";
48
import { useClipboard } from "hooks/useClipboard";
5-
import { CheckIcon } from "lucide-react";
6-
import { type ReactNode, forwardRef } from "react";
7-
import { FileCopyIcon } from "../Icons/FileCopyIcon";
9+
import { CheckIcon, CopyIcon } from "lucide-react";
10+
import type { FC } from "react";
811

9-
interface CopyButtonProps {
10-
children?: ReactNode;
12+
type CopyButtonProps = ButtonProps & {
1113
text: string;
12-
ctaCopy?: string;
13-
wrapperStyles?: Interpolation<Theme>;
14-
buttonStyles?: Interpolation<Theme>;
15-
tooltipTitle?: string;
16-
}
17-
18-
const Language = {
19-
tooltipTitle: "Copy to clipboard",
20-
ariaLabel: "Copy to clipboard",
14+
label: string;
2115
};
2216

23-
/**
24-
* Copy button used inside the CodeBlock component internally
25-
*/
26-
export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
27-
(props, ref) => {
28-
const {
29-
text,
30-
ctaCopy,
31-
wrapperStyles,
32-
buttonStyles,
33-
tooltipTitle = Language.tooltipTitle,
34-
} = props;
35-
const { showCopiedSuccess, copyToClipboard } = useClipboard({
36-
textToCopy: text,
37-
});
17+
export const CopyButton: FC<CopyButtonProps> = ({
18+
text,
19+
label,
20+
...buttonProps
21+
}) => {
22+
const { showCopiedSuccess, copyToClipboard } = useClipboard({
23+
textToCopy: text,
24+
});
3825

39-
return (
40-
<Tooltip title={tooltipTitle} placement="top">
41-
<div css={[{ display: "flex" }, wrapperStyles]}>
42-
<IconButton
43-
ref={ref}
44-
css={[styles.button, buttonStyles]}
45-
size="small"
46-
aria-label={Language.ariaLabel}
47-
variant="text"
26+
return (
27+
<TooltipProvider>
28+
<Tooltip>
29+
<TooltipTrigger asChild>
30+
<Button
31+
size="icon"
32+
variant="subtle"
4833
onClick={copyToClipboard}
34+
{...buttonProps}
4935
>
50-
{showCopiedSuccess ? (
51-
<CheckIcon css={styles.copyIcon} />
52-
) : (
53-
<FileCopyIcon css={styles.copyIcon} />
54-
)}
55-
{ctaCopy && <div css={{ marginLeft: 8 }}>{ctaCopy}</div>}
56-
</IconButton>
57-
</div>
36+
{showCopiedSuccess ? <CheckIcon /> : <CopyIcon />}
37+
<span className="sr-only">{label}</span>
38+
</Button>
39+
</TooltipTrigger>
40+
<TooltipContent>{label}</TooltipContent>
5841
</Tooltip>
59-
);
60-
},
61-
);
62-
63-
const styles = {
64-
button: (theme) => css`
65-
border-radius: 8px;
66-
padding: 8px;
67-
min-width: 32px;
68-
69-
&:hover {
70-
background: ${theme.palette.background.paper};
71-
}
72-
`,
73-
copyIcon: css`
74-
width: 20px;
75-
height: 20px;
76-
`,
77-
} satisfies Record<string, Interpolation<Theme>>;
42+
</TooltipProvider>
43+
);
44+
};

site/src/components/GitDeviceAuth/GitDeviceAuth.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ export const GitDeviceAuth: FC<GitDeviceAuthProps> = ({
134134
Copy your one-time code:&nbsp;
135135
<div css={styles.copyCode}>
136136
<span css={styles.code}>{externalAuthDevice.user_code}</span>
137-
&nbsp; <CopyButton text={externalAuthDevice.user_code} />
137+
&nbsp;{" "}
138+
<CopyButton
139+
text={externalAuthDevice.user_code}
140+
label="Copy user code"
141+
/>
138142
</div>
139143
<br />
140144
Then open the link below and paste it:

site/src/components/Icons/FileCopyIcon.tsx

-10
This file was deleted.

site/src/modules/dashboard/Navbar/UserDropdown/UserDropdownContent.tsx

+2-10
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,7 @@ export const UserDropdownContent: FC<UserDropdownContentProps> = ({
151151
</Tooltip>
152152
<CopyButton
153153
text={buildInfo.deployment_id}
154-
buttonStyles={css`
155-
width: 16px;
156-
height: 16px;
157-
158-
svg {
159-
width: 16px;
160-
height: 16px;
161-
}
162-
`}
154+
label="Copy deployment ID"
163155
/>
164156
</div>
165157
)}
@@ -181,7 +173,7 @@ const GithubStar: FC<SvgIconProps> = (props) => (
181173
fill="currentColor"
182174
{...props}
183175
>
184-
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path>
176+
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z" />
185177
</svg>
186178
);
187179

site/src/modules/provisioners/ProvisionerTag.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import type { Interpolation, Theme } from "@emotion/react";
2-
import CloseIcon from "@mui/icons-material/Close";
32
import IconButton from "@mui/material/IconButton";
43
import { Pill } from "components/Pill/Pill";
5-
import { CircleCheck as CircleCheckIcon } from "lucide-react";
6-
import { CircleMinus as CircleMinusIcon } from "lucide-react";
7-
import { Tag as TagIcon } from "lucide-react";
4+
import { CircleCheckIcon, CircleMinusIcon, TagIcon, XIcon } from "lucide-react";
85
import type { ComponentProps, FC } from "react";
96

107
const parseBool = (s: string): { valid: boolean; value: boolean } => {
@@ -51,7 +48,7 @@ export const ProvisionerTag: FC<ProvisionerTagProps> = ({
5148
onDelete(tagName);
5249
}}
5350
>
54-
<CloseIcon fontSize="inherit" css={{ width: 14, height: 14 }} />
51+
<XIcon className="size-icon-xs" />
5552
<span className="sr-only">Delete {tagName}</span>
5653
</IconButton>
5754
</>

0 commit comments

Comments
 (0)