mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(site): use custom application name (#9902)
This commit is contained in:
+1
-1
@@ -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,
|
||||
|
||||
+33
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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) && (
|
||||
|
||||
@@ -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 : "";
|
||||
};
|
||||
Reference in New Issue
Block a user