Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/src/modules/modular_login/FJLogin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ const FJInstanceLogin = ({ opened, onClose, goBack, setRepoSelection, selectedRe
<Button type="submit" mt="md">
Login
</Button>
<Button variant="outline" mt="md" ml="sm" onClick={() => {if(instanceData.length == 0) {setRepoSelection("")} else goBack(false)}}>
Register
</Button>
<Button variant="outline" mt="md" ml="sm" onClick={() => {if(instanceData.length == 0) {setRepoSelection("")} else goBack(false)}}>
Back
</Button>
Expand Down
20 changes: 8 additions & 12 deletions frontend/src/modules/modular_login/SBHLogin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const getProfile = async (instance, auth) => {
}
};

const SBHInstanceLogin = ({ goBack, setRepoSelection }) => {
const SBHInstanceLogin = ({ selectedRepo, navigateTo, goBack, setRepoSelection }) => {
const [instanceData, setInstanceData] = useLocalStorage({ key: 'SynbioHub', defaultValue: [] });
const dispatch = useDispatch();
const selected = useSelector(state => state.primaryRepository.sbhPrimary);
Expand Down Expand Up @@ -141,17 +141,13 @@ const SBHInstanceLogin = ({ goBack, setRepoSelection }) => {
<Button type="submit" mt="md">
Login
</Button>
<Button
variant="outline"
mt="md"
ml="sm"
onClick={() => {
if (instanceData.length === 0) {
setRepoSelection('');
} else {
goBack(false);
}
}}
<Button variant="outline" mt="md" ml="sm" onClick={() => {
if (instanceData.length === 0) {
setRepoSelection('');
} else {
goBack(false);
}
}}
>
Back
</Button>
Expand Down
31 changes: 26 additions & 5 deletions frontend/src/modules/modular_login/SBHOnly.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { setSBHPrimary } from '../../redux/slices/primaryRepositorySlice';
import { SBHLogin, CheckLogin } from '../../API';

const SBHOnly = ({opened, onClose, goBack}) => {
const SBHOnly = ({opened, onClose, goBack, navigateTo, selectedRepo}) => {
const [instanceData, setInstanceData] = useLocalStorage({ key: "SynbioHub", defaultValue: [] });
const dispatch = useDispatch();
const selected = useSelector(state => state.primaryRepository.sbhPrimary);
Expand Down Expand Up @@ -115,6 +115,12 @@ const SBHOnly = ({opened, onClose, goBack}) => {
}
};

const handleRegister = () => {
navigateTo('sbh-register', {
selectedRepo: selected
})
}

return (
<Modal
opened={opened}
Expand All @@ -138,13 +144,28 @@ const SBHOnly = ({opened, onClose, goBack}) => {
/>
<Group position="apart" mt="xl">
{goBack && (
<Button variant="default" onClick={goBack}>
<Button
type="button"
variant="default"
onClick={goBack}
>
Back
</Button>
)}
<Button type="submit" ml={goBack ? undefined : "auto"}>
Login
</Button>

<Group ml={goBack ? undefined : "auto"}>
<Button
type="button"
variant="outline"
onClick={handleRegister}
>
Register
</Button>

<Button type="submit">
Login
</Button>
</Group>
</Group>
</form>
</Modal>
Expand Down
195 changes: 195 additions & 0 deletions frontend/src/modules/modular_login/SBHRegister.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import {
Button,
Group,
PasswordInput,
Stack,
TextInput,
} from '@mantine/core'
import { useState } from 'react'
import axios from 'axios'

export default function SBHRegister({
selectedRepo,
onComplete,
goBack,
}) {
const [fullName, setFullName] = useState('')
const [affiliation, setAffiliation] = useState('')
const [email, setEmail] = useState('')
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')

const [error, setError] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)

const handleRegister = async () => {
setError('')

if (!fullName.trim()) {
setError('Full Name is required.')
return
}

if (!email.trim()) {
setError('Email Address is required.')
return
}

if (!username.trim()) {
setError('User Name is required.')
return
}

if (!password) {
setError('Password is required.')
return
}

if (password !== confirmPassword) {
setError('Passwords do not match.')
return
}

if (!selectedRepo) {
setError('No SynBioHub repository selected.')
return
}

setIsSubmitting(true)

try {
const params = new URLSearchParams()

params.append('name', fullName.trim())
params.append('affiliation', affiliation.trim())
params.append('email', email.trim())
params.append('username', username.trim())
params.append('password1', password)
params.append('password2', confirmPassword)

const baseUrl = selectedRepo.replace(/\/+$/, '')

await axios.post(
`${baseUrl}/register`,
params,
{
headers: {
'Content-Type':
'application/x-www-form-urlencoded',
},
}
)

onComplete?.({
completed: true,
username: username.trim(),
email: email.trim(),
})
} catch (err) {
console.error('SynBioHub registration failed:', err)

const message =
err?.response?.data?.message ||
err?.response?.data?.error ||
(typeof err?.response?.data === 'string'
? err.response.data
: null) ||
err.message ||
'Unable to register with SynBioHub.'

setError(message)
} finally {
setIsSubmitting(false)
}
}

return (
<Stack>
<TextInput
label="Full Name"
placeholder="Full Name"
required
value={fullName}
onChange={event =>
setFullName(event.currentTarget.value)
}
/>

<TextInput
label="Affiliation"
placeholder="Affiliation"
description="Optional"
value={affiliation}
onChange={event =>
setAffiliation(event.currentTarget.value)
}
/>

<TextInput
label="Email Address"
placeholder="name@example.com"
type="email"
required
value={email}
onChange={event =>
setEmail(event.currentTarget.value)
}
/>

<TextInput
label="User Name"
placeholder="User Name"
required
value={username}
onChange={event =>
setUsername(event.currentTarget.value)
}
/>

<PasswordInput
label="Password"
required
value={password}
onChange={event =>
setPassword(event.currentTarget.value)
}
/>

<PasswordInput
label="Confirm Password"
required
value={confirmPassword}
onChange={event =>
setConfirmPassword(event.currentTarget.value)
}
/>

{error && (
<div style={{ color: 'red', fontSize: 14 }}>
{error}
</div>
)}

<Group position="apart" mt="md">
{goBack && (
<Button
variant="default"
onClick={goBack}
disabled={isSubmitting}
>
Back
</Button>
)}

<Button
onClick={handleRegister}
loading={isSubmitting}
ml={goBack ? 0 : 'auto'}
>
Register
</Button>
</Group>
</Stack>
)
}
Loading
Loading