Skip to content

Commit 6a6272b

Browse files
committed
form
1 parent 40ee863 commit 6a6272b

File tree

5 files changed

+123
-49
lines changed

5 files changed

+123
-49
lines changed

coderd/users.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ func (api *API) putUserAppearanceSettings(rw http.ResponseWriter, r *http.Reques
10431043

10441044
updatedTerminalFont, err := api.Database.UpdateUserTerminalFont(ctx, database.UpdateUserTerminalFontParams{
10451045
UserID: user.ID,
1046-
TerminalFont: string(params.ThemePreference),
1046+
TerminalFont: string(params.TerminalFont),
10471047
})
10481048
if err != nil {
10491049
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{

site/site.go

+11
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state ht
428428
var eg errgroup.Group
429429
var user database.User
430430
var themePreference string
431+
var terminalFont string
431432
orgIDs := []uuid.UUID{}
432433
eg.Go(func() error {
433434
var err error
@@ -443,6 +444,15 @@ func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state ht
443444
}
444445
return err
445446
})
447+
eg.Go(func() error {
448+
var err error
449+
terminalFont, err = h.opts.Database.GetUserTerminalFont(ctx, apiKey.UserID)
450+
if errors.Is(err, sql.ErrNoRows) {
451+
terminalFont = ""
452+
return nil
453+
}
454+
return err
455+
})
446456
eg.Go(func() error {
447457
memberIDs, err := h.opts.Database.GetOrganizationIDsByMemberIDs(ctx, []uuid.UUID{apiKey.UserID})
448458
if errors.Is(err, sql.ErrNoRows) || len(memberIDs) == 0 {
@@ -471,6 +481,7 @@ func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state ht
471481
defer wg.Done()
472482
userAppearance, err := json.Marshal(codersdk.UserAppearanceSettings{
473483
ThemePreference: themePreference,
484+
TerminalFont: codersdk.TerminalFontName(terminalFont),
474485
})
475486
if err == nil {
476487
state.UserAppearance = html.EscapeString(string(userAppearance))

site/src/api/queries/users.ts

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ export const updateAppearanceSettings = (
251251
// more responsive.
252252
queryClient.setQueryData(myAppearanceKey, {
253253
theme_preference: patch.theme_preference,
254+
terminal_font: patch.terminal_font,
254255
});
255256
},
256257
onSuccess: async () =>

site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx

+101-24
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
import type { Interpolation } from "@emotion/react";
2+
import CircularProgress from "@mui/material/CircularProgress";
3+
import FormControl from "@mui/material/FormControl";
4+
import FormControlLabel from "@mui/material/FormControlLabel";
5+
import Radio from "@mui/material/Radio";
6+
import RadioGroup from "@mui/material/RadioGroup";
27
import { visuallyHidden } from "@mui/utils";
3-
import type { UpdateUserAppearanceSettingsRequest } from "api/typesGenerated";
8+
import {
9+
type TerminalFontName,
10+
TerminalFontNames,
11+
type UpdateUserAppearanceSettingsRequest,
12+
} from "api/typesGenerated";
413
import { ErrorAlert } from "components/Alert/ErrorAlert";
514
import { PreviewBadge } from "components/Badges/Badges";
615
import { Stack } from "components/Stack/Stack";
716
import { ThemeOverride } from "contexts/ThemeProvider";
817
import type { FC } from "react";
9-
import themes, { DEFAULT_TERMINAL_FONT, DEFAULT_THEME, type Theme } from "theme";
18+
import themes, {
19+
DEFAULT_TERMINAL_FONT,
20+
DEFAULT_THEME,
21+
type Theme,
22+
} from "theme";
23+
import { Section } from "../Section";
1024

1125
export interface AppearanceFormProps {
1226
isUpdating?: boolean;
@@ -22,44 +36,107 @@ export const AppearanceForm: FC<AppearanceFormProps> = ({
2236
initialValues,
2337
}) => {
2438
const currentTheme = initialValues.theme_preference || DEFAULT_THEME;
25-
const currentTerminalFont = initialValues.terminal_font || DEFAULT_TERMINAL_FONT;
39+
const currentTerminalFont =
40+
initialValues.terminal_font || DEFAULT_TERMINAL_FONT;
2641

2742
const onChangeTheme = async (theme: string) => {
2843
if (isUpdating) {
2944
return;
3045
}
46+
await onSubmit({
47+
theme_preference: theme,
48+
terminal_font: currentTerminalFont,
49+
});
50+
};
3151

32-
await onSubmit({ theme_preference: theme, terminal_font: currentTerminalFont });
52+
const onChangeTerminalFont = async (terminalFont: TerminalFontName) => {
53+
if (isUpdating) {
54+
return;
55+
}
56+
await onSubmit({
57+
theme_preference: currentTheme,
58+
terminal_font: terminalFont,
59+
});
3360
};
3461

3562
return (
3663
<form>
3764
{Boolean(error) && <ErrorAlert error={error} />}
3865

39-
<Stack direction="row" wrap="wrap">
40-
<AutoThemePreviewButton
41-
displayName="Auto"
42-
active={currentTheme === "auto"}
43-
themes={[themes.dark, themes.light]}
44-
onSelect={() => onChangeTheme("auto")}
45-
/>
46-
<ThemePreviewButton
47-
displayName="Dark"
48-
active={currentTheme === "dark"}
49-
theme={themes.dark}
50-
onSelect={() => onChangeTheme("dark")}
51-
/>
52-
<ThemePreviewButton
53-
displayName="Light"
54-
active={currentTheme === "light"}
55-
theme={themes.light}
56-
onSelect={() => onChangeTheme("light")}
57-
/>
58-
</Stack>
66+
<Section
67+
title={
68+
<Stack direction="row" alignItems="center">
69+
<span>Theme</span>
70+
{isUpdating && <CircularProgress size={16} />}
71+
</Stack>
72+
}
73+
layout="fluid"
74+
>
75+
<Stack direction="row" wrap="wrap">
76+
<AutoThemePreviewButton
77+
displayName="Auto"
78+
active={currentTheme === "auto"}
79+
themes={[themes.dark, themes.light]}
80+
onSelect={() => onChangeTheme("auto")}
81+
/>
82+
<ThemePreviewButton
83+
displayName="Dark"
84+
active={currentTheme === "dark"}
85+
theme={themes.dark}
86+
onSelect={() => onChangeTheme("dark")}
87+
/>
88+
<ThemePreviewButton
89+
displayName="Light"
90+
active={currentTheme === "light"}
91+
theme={themes.light}
92+
onSelect={() => onChangeTheme("light")}
93+
/>
94+
</Stack>
95+
</Section>
96+
<div css={{ marginBottom: 48 }}></div>
97+
<Section
98+
title={
99+
<Stack direction="row" alignItems="center">
100+
<span>Terminal Font</span>
101+
{isUpdating && <CircularProgress size={16} />}
102+
</Stack>
103+
}
104+
layout="fluid"
105+
>
106+
<FormControl>
107+
<RadioGroup
108+
aria-labelledby="demo-radio-buttons-group-label"
109+
defaultValue={currentTerminalFont}
110+
name="radio-buttons-group"
111+
onChange={(_, value) =>
112+
onChangeTerminalFont(toTerminalFontName(value))
113+
}
114+
>
115+
<FormControlLabel
116+
value="ibm-plex-mono"
117+
control={<Radio />}
118+
label={
119+
<div css={{ fontFamily: "IBM Plex Mono" }}>IBM Plex Mono</div>
120+
}
121+
/>
122+
<FormControlLabel
123+
value="fira-code"
124+
control={<Radio />}
125+
label={<div css={{ fontFamily: "Fira Code" }}>Fira Code</div>}
126+
/>
127+
</RadioGroup>
128+
</FormControl>
129+
</Section>
59130
</form>
60131
);
61132
};
62133

134+
export function toTerminalFontName(value: string): TerminalFontName {
135+
return TerminalFontNames.includes(value as TerminalFontName)
136+
? (value as TerminalFontName)
137+
: "";
138+
}
139+
63140
interface AutoThemePreviewButtonProps extends Omit<ThemePreviewProps, "theme"> {
64141
themes: [Theme, Theme];
65142
onSelect?: () => void;

site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx

+9-24
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import CircularProgress from "@mui/material/CircularProgress";
21
import { updateAppearanceSettings } from "api/queries/users";
32
import { appearanceSettings } from "api/queries/users";
43
import { ErrorAlert } from "components/Alert/ErrorAlert";
54
import { Loader } from "components/Loader/Loader";
6-
import { Stack } from "components/Stack/Stack";
75
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
86
import type { FC } from "react";
97
import { useMutation, useQuery, useQueryClient } from "react-query";
10-
import { Section } from "../Section";
118
import { AppearanceForm } from "./AppearanceForm";
129

1310
export const AppearancePage: FC = () => {
@@ -31,27 +28,15 @@ export const AppearancePage: FC = () => {
3128

3229
return (
3330
<>
34-
<Section
35-
title={
36-
<Stack direction="row" alignItems="center">
37-
<span>Theme</span>
38-
{updateAppearanceSettingsMutation.isLoading && (
39-
<CircularProgress size={16} />
40-
)}
41-
</Stack>
42-
}
43-
layout="fluid"
44-
>
45-
<AppearanceForm
46-
isUpdating={updateAppearanceSettingsMutation.isLoading}
47-
error={updateAppearanceSettingsMutation.error}
48-
initialValues={{
49-
theme_preference: appearanceSettingsQuery.data.theme_preference,
50-
terminal_font: appearanceSettingsQuery.data.terminal_font,
51-
}}
52-
onSubmit={updateAppearanceSettingsMutation.mutateAsync}
53-
/>
54-
</Section>
31+
<AppearanceForm
32+
isUpdating={updateAppearanceSettingsMutation.isLoading}
33+
error={updateAppearanceSettingsMutation.error}
34+
initialValues={{
35+
theme_preference: appearanceSettingsQuery.data.theme_preference,
36+
terminal_font: appearanceSettingsQuery.data.terminal_font,
37+
}}
38+
onSubmit={updateAppearanceSettingsMutation.mutateAsync}
39+
/>
5540
</>
5641
);
5742
};

0 commit comments

Comments
 (0)