Files
fredy/ui/src/views/login/Login.jsx
AdriDevelopsThings 6c7d655277 added redirect after login (#325)
The old behaviour was: You open a page without being authorized, you are getting redirected to /login that
redirects you after a successful authentication to /dashboard. This is really annoying if you want to open
listenings directly from your notification adapter for example. This commit introduces a method to redirect
you back to the original page you opened after the authentication process by adding the navigation of the
opened page as state to the navigation to /login. The login component than unpacks the state that contains
the old navigation and redirects the user back to path from the original navigation. The path /dashboard is
used as a fallback if no navigation in the state is present.
2026-06-09 11:59:18 +02:00

123 lines
3.5 KiB
JavaScript

/*
* Copyright (c) 2026 by Christian Kellner.
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
*/
import React, { useEffect } from 'react';
import cityBackground from '../../assets/city_background.jpg';
import Logo from '../../components/logo/Logo';
import { xhrPost } from '../../services/xhr';
import { useLocation, useNavigate } from 'react-router-dom';
import { useActions, useSelector } from '../../services/state/store';
import { Input, Button, Banner } from '@douyinfe/semi-ui-19';
import './login.less';
import { IconUser, IconLock } from '@douyinfe/semi-icons';
import { useTranslation } from '../../services/i18n/i18n.jsx';
export default function Login() {
const t = useTranslation();
const actions = useActions();
const [username, setUserName] = React.useState('');
const [password, setPassword] = React.useState('');
const [error, setError] = React.useState(null);
const demoMode = useSelector((state) => state.demoMode.demoMode || false);
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
async function init() {
await actions.demoMode.getDemoMode();
}
init();
}, []);
const tryLogin = async () => {
if (!username?.trim() || !password) {
setError(t('login.errorMandatory'));
return;
}
setError(null);
try {
await xhrPost('/api/login', {
username: username.trim(),
password,
});
/* eslint-disable no-unused-vars */
} catch (ignored) {
setError(t('login.errorInvalid'));
return;
}
await actions.user.getCurrentUser();
navigate(location.state?.from?.pathname || '/dashboard');
};
return (
<div className="login">
<div className="login__bgImage" style={{ background: `url("${cityBackground}")` }} />
<div className="login__loginWrapper">
<div className="login__logoWrapper">
<Logo width={250} white />
</div>
{demoMode && (
<Banner
fullMode={true}
type="info"
bordered
closeIcon={null}
description={t('login.demoBanner')}
style={{ marginBottom: '1.5rem' }}
/>
)}
<form onSubmit={(e) => e.preventDefault()}>
{error && <Banner type="danger" closeIcon={null} description={error} style={{ marginBottom: '1rem' }} />}
<div className="login__inputGroup">
<Input
size="large"
prefix={<IconUser />}
placeholder={t('login.usernamePlaceholder')}
value={username}
showClear
autoFocus
onChange={(value) => setUserName(value)}
onKeyPress={async (e) => {
if (e.key === 'Enter') {
await tryLogin();
}
}}
/>
</div>
<div className="login__inputGroup">
<Input
size="large"
mode="password"
prefix={<IconLock />}
value={password}
placeholder={t('login.passwordPlaceholder')}
onChange={(value) => setPassword(value)}
onKeyPress={async (e) => {
if (e.key === 'Enter') {
await tryLogin();
}
}}
/>
</div>
<Button block type="primary" onClick={tryLogin} theme="solid" style={{ marginTop: '1rem' }}>
{t('login.loginButton')}
</Button>
</form>
</div>
</div>
);
}
Login.displayName = 'Login';