diff --git a/app/components/Input.tsx b/app/components/Input.tsx index bb8893d4b..fd13ff7ae 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -175,6 +175,7 @@ function Input( labelHidden, onFocus, onBlur, + children, ...rest } = props; @@ -211,6 +212,7 @@ function Input( {...rest} /> )} + {children} {error && ( diff --git a/app/scenes/Login/index.tsx b/app/scenes/Login/index.tsx index 30d678bb1..7b6d9fea2 100644 --- a/app/scenes/Login/index.tsx +++ b/app/scenes/Login/index.tsx @@ -15,6 +15,7 @@ import Fade from "~/components/Fade"; import Flex from "~/components/Flex"; import Heading from "~/components/Heading"; import OutlineIcon from "~/components/Icons/OutlineIcon"; +import Input from "~/components/Input"; import LoadingIndicator from "~/components/LoadingIndicator"; import PageTitle from "~/components/PageTitle"; import TeamLogo from "~/components/TeamLogo"; @@ -34,11 +35,11 @@ function Header({ config }: { config?: Config | undefined }) { const { t } = useTranslation(); const isSubdomain = !!config?.hostname; - if ( - !isCloudHosted || - parseDomain(window.location.origin).custom || - Desktop.isElectron() - ) { + if (!isCloudHosted || parseDomain(window.location.origin).custom) { + return null; + } + + if (Desktop.isElectron() && !isSubdomain) { return null; } @@ -56,6 +57,8 @@ type Props = { function Login({ children }: Props) { const location = useLocation(); const query = useQuery(); + const notice = query.get("notice"); + const { t, i18n } = useTranslation(); const { auth } = useStores(); const { config } = auth; @@ -74,6 +77,22 @@ function Login({ children }: Props) { setEmailLinkSentTo(email); }, []); + const handleGoSubdomain = React.useCallback(async (event) => { + event.preventDefault(); + const data = Object.fromEntries(new FormData(event.target)); + const normalizedSubdomain = data.subdomain + .toString() + .toLowerCase() + .trim() + .replace(/^https?:\/\//, ""); + const host = `https://${normalizedSubdomain}.getoutline.com`; + await Desktop.bridge.addCustomHost(host); + + setTimeout(() => { + window.location.href = host; + }, 500); + }, []); + React.useEffect(() => { auth.fetchConfig().catch(setError); }, [auth]); @@ -160,6 +179,43 @@ function Login({ children }: Props) { ); } + if (Desktop.isElectron() && notice === "domain-required") { + return ( + +
+ + + {t("Choose workspace")} + + {t( + "This login method requires choosing your workspace to continue" + )} + … + + + + .getoutline.com + + + + {t("Continue")} + + + + ); + } + const hasMultipleProviders = config.providers.length > 1; const defaultProvider = find( config.providers, @@ -275,6 +331,11 @@ const StyledHeading = styled(Heading)` margin: 0; `; +const Domain = styled.div` + color: ${s("textSecondary")}; + padding: 0 8px 0 0; +`; + const CheckEmailIcon = styled(EmailIcon)` margin-bottom: -1.5em; `; diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 38c1d37b0..26b36303e 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -633,6 +633,9 @@ "Custom domain setup": "Custom domain setup", "Almost there": "Almost there", "Your custom domain is successfully pointing at Outline. To complete the setup process please contact support.": "Your custom domain is successfully pointing at Outline. To complete the setup process please contact support.", + "Choose workspace": "Choose workspace", + "This login method requires choosing your workspace to continue": "This login method requires choosing your workspace to continue", + "subdomain": "subdomain", "Check your email": "Check your email", "A magic sign-in link has been sent to the email {{ emailLinkSentTo }} if an account exists.": "A magic sign-in link has been sent to the email {{ emailLinkSentTo }} if an account exists.", "Back to login": "Back to login",