feat(site): use custom application name (#9902)

This commit is contained in:
Marcin Tojek
2023-09-28 18:23:27 +02:00
committed by GitHub
parent 0f946669c1
commit 305556f655
6 changed files with 74 additions and 4 deletions
@@ -6,7 +6,7 @@ const meta: Meta<typeof AppearanceSettingsPageView> = {
component: AppearanceSettingsPageView,
args: {
appearance: {
application_name: "",
application_name: "Foobar",
logo_url: "https://github.com/coder.png",
service_banner: {
enabled: true,
@@ -42,6 +42,16 @@ export const AppearanceSettingsPageView = ({
const styles = useStyles();
const theme = useTheme();
const applicationNameForm = useFormik<{
application_name: string;
}>({
initialValues: {
application_name: appearance.application_name,
},
onSubmit: (values) => onSaveAppearance(values, false),
});
const applicationNameFieldHelpers = getFormHelpers(applicationNameForm);
const logoForm = useFormik<{
logo_url: string;
}>({
@@ -87,6 +97,22 @@ export const AppearanceSettingsPageView = ({
<EnterpriseBadge />
</Badges>
<Fieldset
title="Application name"
subtitle="Specify a custom application name to be displayed on the login page."
validation={!isEntitled ? "This is an Enterprise only feature." : ""}
onSubmit={applicationNameForm.handleSubmit}
button={!isEntitled && <Button disabled>Submit</Button>}
>
<TextField
{...applicationNameFieldHelpers("application_name")}
defaultValue={appearance.application_name}
fullWidth
placeholder='Leave empty to display "Coder".'
disabled={!isEntitled}
/>
</Fieldset>
<Fieldset
title="Logo URL"
subtitle="Specify a custom URL for your logo to be displayed in the top left
@@ -99,6 +125,13 @@ export const AppearanceSettingsPageView = ({
onSubmit={logoForm.handleSubmit}
button={!isEntitled && <Button disabled>Submit</Button>}
>
<TextField
{...logoFieldHelpers("application_name")}
defaultValue={appearance.application_name}
fullWidth
placeholder='Leave empty to display "Coder".'
disabled={!isEntitled}
/>
<TextField
{...logoFieldHelpers("logo_url")}
defaultValue={appearance.logo_url}
+3 -1
View File
@@ -4,11 +4,13 @@ import { Helmet } from "react-helmet-async";
import { Navigate, useLocation } from "react-router-dom";
import { retrieveRedirect } from "utils/redirect";
import { LoginPageView } from "./LoginPageView";
import { getApplicationName } from "utils/appearance";
export const LoginPage: FC = () => {
const location = useLocation();
const [authState, authSend] = useAuth();
const redirectTo = retrieveRedirect(location.search);
const applicationName = getApplicationName();
if (authState.matches("signedIn")) {
return <Navigate to={redirectTo} replace />;
@@ -18,7 +20,7 @@ export const LoginPage: FC = () => {
return (
<>
<Helmet>
<title>Sign in to Coder</title>
<title>Sign in to {applicationName}</title>
</Helmet>
<LoginPageView
context={authState.context}
+18 -1
View File
@@ -6,6 +6,7 @@ import { AuthContext, UnauthenticatedData } from "xServices/auth/authXService";
import { SignInForm } from "./SignInForm";
import { retrieveRedirect } from "utils/redirect";
import { CoderIcon } from "components/Icons/CoderIcon";
import { getApplicationName, getLogoURL } from "utils/appearance";
export interface LoginPageViewProps {
context: AuthContext;
@@ -28,13 +29,29 @@ export const LoginPageView: FC<LoginPageViewProps> = ({
// This allows messages to be displayed at the top of the sign in form.
// Helpful for any redirects that want to inform the user of something.
const info = new URLSearchParams(location.search).get("info") || undefined;
const applicationName = getApplicationName();
const logoURL = getLogoURL();
const applicationLogo = logoURL ? (
<div>
<img
alt={applicationName}
src={logoURL}
// This prevent browser to display the ugly error icon if the
// image path is wrong or user didn't finish typing the url
onError={(e) => (e.currentTarget.style.display = "none")}
onLoad={(e) => (e.currentTarget.style.display = "inline")}
/>
</div>
) : (
<CoderIcon fill="white" opacity={1} className={styles.icon} />
);
return isLoading ? (
<FullScreenLoader />
) : (
<div className={styles.root}>
<div className={styles.container}>
<CoderIcon fill="white" opacity={1} className={styles.icon} />
{applicationLogo}
<SignInForm
authMethods={data.authMethods}
redirectTo={redirectTo}
+3 -1
View File
@@ -9,6 +9,7 @@ import Button from "@mui/material/Button";
import EmailIcon from "@mui/icons-material/EmailOutlined";
import { Alert } from "components/Alert/Alert";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { getApplicationName } from "utils/appearance";
export const Language = {
emailLabel: "Email",
@@ -90,11 +91,12 @@ export const SignInForm: FC<React.PropsWithChildren<SignInFormProps>> = ({
// Hide password auth by default if any OAuth method is enabled
const [showPasswordAuth, setShowPasswordAuth] = useState(!oAuthEnabled);
const styles = useStyles();
const applicationName = getApplicationName();
return (
<div className={styles.root}>
<h1 className={styles.title}>
Sign in to <strong>Coder</strong>
Sign in to <strong>{applicationName}</strong>
</h1>
{Boolean(error) && (
+16
View File
@@ -0,0 +1,16 @@
export const getApplicationName = (): string => {
const c = document.head
.querySelector(`meta[name=application-name]`)
?.getAttribute("content");
// Fallback to "Coder" if the application name is not available for some reason.
// We need to check if the content does not look like {{ .ApplicationName}}
// as it means that Coder is running in development mode (port :8080).
return c && !c.startsWith("{{ .") ? c : "Coder";
};
export const getLogoURL = (): string => {
const c = document.head
.querySelector(`meta[property=logo-url]`)
?.getAttribute("content");
return c && !c.startsWith("{{ .") ? c : "";
};