Skip to content

Commit c5173c1

Browse files
committed
site: use custom application name
1 parent dae528f commit c5173c1

File tree

5 files changed

+72
-3
lines changed

5 files changed

+72
-3
lines changed

site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ export const AppearanceSettingsPageView = ({
4242
const styles = useStyles();
4343
const theme = useTheme();
4444

45+
const applicationNameForm = useFormik<{
46+
application_name: string;
47+
}>({
48+
initialValues: {
49+
application_name: appearance.application_name,
50+
},
51+
onSubmit: (values) => onSaveAppearance(values, false),
52+
});
53+
const applicationNameFieldHelpers = getFormHelpers(applicationNameForm);
54+
4555
const logoForm = useFormik<{
4656
logo_url: string;
4757
}>({
@@ -87,6 +97,22 @@ export const AppearanceSettingsPageView = ({
8797
<EnterpriseBadge />
8898
</Badges>
8999

100+
<Fieldset
101+
title="Application name"
102+
subtitle="Specify a custom application name to be displayed on the login page."
103+
validation={!isEntitled ? "This is an Enterprise only feature." : ""}
104+
onSubmit={applicationNameForm.handleSubmit}
105+
button={!isEntitled && <Button disabled>Submit</Button>}
106+
>
107+
<TextField
108+
{...applicationNameFieldHelpers("application_name")}
109+
defaultValue={appearance.application_name}
110+
fullWidth
111+
placeholder='Leave empty to display "Coder".'
112+
disabled={!isEntitled}
113+
/>
114+
</Fieldset>
115+
90116
<Fieldset
91117
title="Logo URL"
92118
subtitle="Specify a custom URL for your logo to be displayed in the top left
@@ -99,6 +125,13 @@ export const AppearanceSettingsPageView = ({
99125
onSubmit={logoForm.handleSubmit}
100126
button={!isEntitled && <Button disabled>Submit</Button>}
101127
>
128+
<TextField
129+
{...logoFieldHelpers("application_name")}
130+
defaultValue={appearance.application_name}
131+
fullWidth
132+
placeholder='Leave empty to display "Coder".'
133+
disabled={!isEntitled}
134+
/>
102135
<TextField
103136
{...logoFieldHelpers("logo_url")}
104137
defaultValue={appearance.logo_url}

site/src/pages/LoginPage/LoginPage.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import { Helmet } from "react-helmet-async";
44
import { Navigate, useLocation } from "react-router-dom";
55
import { retrieveRedirect } from "../../utils/redirect";
66
import { LoginPageView } from "./LoginPageView";
7+
import { getApplicationName } from "utils/appearance";
78

89
export const LoginPage: FC = () => {
910
const location = useLocation();
1011
const [authState, authSend] = useAuth();
1112
const redirectTo = retrieveRedirect(location.search);
13+
const applicationName = getApplicationName();
1214

1315
if (authState.matches("signedIn")) {
1416
return <Navigate to={redirectTo} replace />;
@@ -18,7 +20,7 @@ export const LoginPage: FC = () => {
1820
return (
1921
<>
2022
<Helmet>
21-
<title>Sign in to Coder</title>
23+
<title>Sign in to {applicationName}</title>
2224
</Helmet>
2325
<LoginPageView
2426
context={authState.context}

site/src/pages/LoginPage/LoginPageView.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { AuthContext, UnauthenticatedData } from "xServices/auth/authXService";
66
import { SignInForm } from "./SignInForm";
77
import { retrieveRedirect } from "utils/redirect";
88
import { CoderIcon } from "components/Icons/CoderIcon";
9+
import { getLogoURL } from "utils/appearance";
910

1011
export interface LoginPageViewProps {
1112
context: AuthContext;
@@ -28,13 +29,28 @@ export const LoginPageView: FC<LoginPageViewProps> = ({
2829
// This allows messages to be displayed at the top of the sign in form.
2930
// Helpful for any redirects that want to inform the user of something.
3031
const info = new URLSearchParams(location.search).get("info") || undefined;
32+
const logoURL = getLogoURL();
33+
const applicationLogo = logoURL ? (
34+
<div>
35+
<img
36+
alt=""
37+
src={logoURL}
38+
// This prevent browser to display the ugly error icon if the
39+
// image path is wrong or user didn't finish typing the url
40+
onError={(e) => (e.currentTarget.style.display = "none")}
41+
onLoad={(e) => (e.currentTarget.style.display = "inline")}
42+
/>
43+
</div>
44+
) : (
45+
<CoderIcon fill="white" opacity={1} className={styles.icon} />
46+
);
3147

3248
return isLoading ? (
3349
<FullScreenLoader />
3450
) : (
3551
<div className={styles.root}>
3652
<div className={styles.container}>
37-
<CoderIcon fill="white" opacity={1} className={styles.icon} />
53+
{applicationLogo}
3854
<SignInForm
3955
authMethods={data.authMethods}
4056
redirectTo={redirectTo}

site/src/pages/LoginPage/SignInForm.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Button from "@mui/material/Button";
99
import EmailIcon from "@mui/icons-material/EmailOutlined";
1010
import { Alert } from "components/Alert/Alert";
1111
import { ErrorAlert } from "components/Alert/ErrorAlert";
12+
import { getApplicationName } from "utils/appearance";
1213

1314
export const Language = {
1415
emailLabel: "Email",
@@ -90,11 +91,12 @@ export const SignInForm: FC<React.PropsWithChildren<SignInFormProps>> = ({
9091
// Hide password auth by default if any OAuth method is enabled
9192
const [showPasswordAuth, setShowPasswordAuth] = useState(!oAuthEnabled);
9293
const styles = useStyles();
94+
const applicationName = getApplicationName();
9395

9496
return (
9597
<div className={styles.root}>
9698
<h1 className={styles.title}>
97-
Sign in to <strong>Coder</strong>
99+
Sign in to <strong>{applicationName}</strong>
98100
</h1>
99101

100102
{Boolean(error) && (

site/src/utils/appearance.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export const getApplicationName = (): string => {
2+
const c = document
3+
.querySelector(`meta[name=application-name]`)
4+
?.getAttribute("content");
5+
// Fallback to "Coder" if the application name is not available for some reason.
6+
// We need to check if the content does not look like {{ .ApplicationName}}
7+
// as it means that Coder is running in development mode (port :8080).
8+
return c && !c.startsWith("{{ .") ? c : "Coder";
9+
};
10+
11+
export const getLogoURL = (): string => {
12+
const c = document
13+
.querySelector(`meta[property=logo-url]`)
14+
?.getAttribute("content");
15+
return c && !c.startsWith("{{ .") ? c : "";
16+
};

0 commit comments

Comments
 (0)