From 1cc502208a7d7ba2648eb71f86ebb0c9698ecaaf Mon Sep 17 00:00:00 2001 From: Brent Salisbury Date: Thu, 7 Nov 2024 13:14:20 -0500 Subject: [PATCH] Add the github Oauth option to the dev login page - Break out the local login into a new client side file to avoid rehydration errors in nextjs v15 Signed-off-by: Brent Salisbury --- src/app/login/locallogin.tsx | 152 +++++++++++++++++++++++++++++++++++ src/app/login/page.tsx | 133 ++++-------------------------- 2 files changed, 168 insertions(+), 117 deletions(-) create mode 100644 src/app/login/locallogin.tsx diff --git a/src/app/login/locallogin.tsx b/src/app/login/locallogin.tsx new file mode 100644 index 00000000..15331d18 --- /dev/null +++ b/src/app/login/locallogin.tsx @@ -0,0 +1,152 @@ +// src/app/login/LocalLogin.tsx +// 'use client'; + +import React, { useState } from 'react'; +import { signIn } from 'next-auth/react'; +import { Grid, GridItem, Text, TextContent, Form, FormGroup, TextInput, Button, HelperText, HelperTextItem } from '@patternfly/react-core'; +import GithubIcon from '@patternfly/react-icons/dist/dynamic/icons/github-icon'; +import './githublogin.css'; + +const LocalLogin: React.FunctionComponent = () => { + const [, setShowHelperText] = useState(false); + const [username, setUsername] = useState(''); + const [isValidUsername, setIsValidUsername] = useState(true); + const [password, setPassword] = useState(''); + const [isValidPassword, setIsValidPassword] = useState(true); + + const handleLogin = async (e: React.FormEvent) => { + e.preventDefault(); + const result = await signIn('credentials', { redirect: false, username, password }); + if (result?.error) { + setShowHelperText(true); + setIsValidUsername(false); + setIsValidPassword(false); + } else { + window.location.href = '/'; + } + }; + + const handleUsernameChange = (_event: React.FormEvent, value: string) => { + setUsername(value); + }; + + const handlePasswordChange = (_event: React.FormEvent, value: string) => { + setPassword(value); + }; + + const handleGitHubLogin = () => { + signIn('github', { callbackUrl: '/' }); + }; + + return ( +
+ + + + Login locally with a username and password or via GitHub OAuth + + + Join the novel, community-based movement to create truly open-source LLMs + +
+ +
+ + + {!isValidUsername && ( + + Invalid Username + + )} + + + + {!isValidPassword && ( + + Invalid password + + )} + + +
+
+ + + + GitHub + {' '} + |{' '} + + Collaborate + {' '} + |{' '} + + Code Of Conduct + + + + + Terms of use + {' '} + |{' '} + + Privacy Policy + + + +
+
+
+ ); +}; + +export default LocalLogin; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 409a0e50..cf5e59ce 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -2,134 +2,33 @@ 'use client'; import React, { useState, useEffect } from 'react'; -import { signIn } from 'next-auth/react'; -import GithubLogin from './githublogin'; -import { Grid, GridItem } from '@patternfly/react-core/dist/dynamic/layouts/Grid'; -import { Text, TextContent } from '@patternfly/react-core/dist/dynamic/components/Text'; -import { Form, FormGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput'; -import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { HelperText, HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import './githublogin.css'; +import LocalLogin from '@/app/login/locallogin'; +import GithubLogin from '@/app/login/githublogin'; const Login: React.FunctionComponent = () => { - const [, setShowHelperText] = useState(false); - const [username, setUsername] = useState(''); - const [isValidUsername, setIsValidUsername] = useState(true); - const [password, setPassword] = useState(''); - const [isValidPassword, setIsValidPassword] = useState(true); - const [isProd, setIsProd] = useState(null); // Use null for initial load state - + const [isProd, setIsProd] = useState(null); useEffect(() => { const chooseLoginPage = async () => { - const res = await fetch('/api/envConfig'); - const envConfig = await res.json(); - setIsProd(envConfig.DEPLOYMENT_TYPE !== 'dev'); + try { + const res = await fetch('/api/envConfig'); + const envConfig = await res.json(); + setIsProd(envConfig.DEPLOYMENT_TYPE !== 'dev'); + } catch (error) { + console.error('Error fetching environment config:', error); + setIsProd(true); + } }; chooseLoginPage(); }, []); - const handleLogin = async (e: React.FormEvent) => { - e.preventDefault(); - const result = await signIn('credentials', { redirect: false, username, password }); - if (result?.error) { - setShowHelperText(true); - setIsValidUsername(false); - setIsValidPassword(false); - } else { - window.location.href = '/'; - } - }; - - const handleUsernameChange = (_event: React.FormEvent, value: string) => { - setUsername(value); - }; - - const handlePasswordChange = (_event: React.FormEvent, value: string) => { - setPassword(value); - }; - - const loginForm = ( -
- - - {!isValidUsername && ( - - Invalid Username - - )} - - - - {!isValidPassword && ( - - Invalid password - - )} - - -
- ); - - const devModeContent = ( -
- - - - Login locally with admin username and password - - - Join the novel, community-based movement to create truly open-source LLMs - -
{loginForm}
- - - - GitHub - {' '} - |{' '} - - Collaborate - {' '} - |{' '} - - Code Of Conduct - - - - - Terms of use - {' '} - |{' '} - - Privacy Policy - - - -
-
-
- ); + if (isProd === null) { + // Render a loading indicator or null while determining the environment + return null; + } - return isProd ? : devModeContent; + return isProd ? : ; }; export default Login;