diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index da75ef05c3..50243fbb21 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -414,7 +414,7 @@ jobs: - name: Set up test data run: invoke setup-test -i - name: Install dependencies - run: cd src/frontend && yarn install + run: inv frontend-compile - name: Install Playwright Browsers run: cd src/frontend && npx playwright install --with-deps - name: Run Playwright tests diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index c562939632..d0e1ded854 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, retries: process.env.CI ? 1 : 0, workers: process.env.CI ? 2 : undefined, - reporter: 'html', + reporter: process.env.CI ? 'github' : 'list', /* Configure projects for major browsers */ projects: [ diff --git a/src/frontend/src/components/forms/AuthFormOptions.tsx b/src/frontend/src/components/forms/AuthFormOptions.tsx new file mode 100644 index 0000000000..373d090bd5 --- /dev/null +++ b/src/frontend/src/components/forms/AuthFormOptions.tsx @@ -0,0 +1,25 @@ +import { Center, Group, Tooltip } from '@mantine/core'; +import { IconServer } from '@tabler/icons-react'; + +import { ColorToggle } from '../items/ColorToggle'; +import { LanguageToggle } from '../items/LanguageToggle'; + +export function AuthFormOptions({ + hostname, + toggleHostEdit +}: { + hostname: string; + toggleHostEdit: () => void; +}) { + return ( +
+ + + + + + + +
+ ); +} diff --git a/src/frontend/src/components/forms/AuthenticationForm.tsx b/src/frontend/src/components/forms/AuthenticationForm.tsx index ed652fd5d1..53f9995b40 100644 --- a/src/frontend/src/components/forms/AuthenticationForm.tsx +++ b/src/frontend/src/components/forms/AuthenticationForm.tsx @@ -16,19 +16,8 @@ import { IconCheck } from '@tabler/icons-react'; import { useNavigate } from 'react-router-dom'; import { doClassicLogin, doSimpleLogin } from '../../functions/auth'; -import { EditButton } from '../items/EditButton'; -export function AuthenticationForm({ - hostname, - editing, - setEditing, - selectElement -}: { - hostname: string; - editing: boolean; - setEditing: (value?: React.SetStateAction | undefined) => void; - selectElement: JSX.Element; -}) { +export function AuthenticationForm() { const classicForm = useForm({ initialValues: { username: '', password: '' } }); @@ -82,10 +71,7 @@ export function AuthenticationForm({ return ( - - {!editing ? hostname : selectElement} - - + Welcome, log in below
{})}> {classicLoginMode ? ( diff --git a/src/frontend/src/components/forms/InstanceOptions.tsx b/src/frontend/src/components/forms/InstanceOptions.tsx new file mode 100644 index 0000000000..d359798b75 --- /dev/null +++ b/src/frontend/src/components/forms/InstanceOptions.tsx @@ -0,0 +1,77 @@ +import { Trans } from '@lingui/macro'; +import { Divider, Group, Select, Text, Title } from '@mantine/core'; +import { useToggle } from '@mantine/hooks'; +import { IconCheck } from '@tabler/icons-react'; + +import { useLocalState } from '../../states/LocalState'; +import { HostList } from '../../states/states'; +import { EditButton } from '../items/EditButton'; +import { HostOptionsForm } from './HostOptionsForm'; + +export function InstanceOptions({ + hostKey, + ChangeHost, + setHostEdit +}: { + hostKey: string; + ChangeHost: (newHost: string) => void; + setHostEdit: () => void; +}) { + const [HostListEdit, setHostListEdit] = useToggle([false, true] as const); + const [setHost, setHostList, hostList] = useLocalState((state) => [ + state.setHost, + state.setHostList, + state.hostList + ]); + + const hostListData = Object.keys(hostList).map((key) => ({ + value: key, + label: hostList[key].name + })); + + function SaveOptions(newHostList: HostList): void { + setHostList(newHostList); + if (newHostList[hostKey] === undefined) { + setHost('', ''); + } + setHostListEdit(); + } + + return ( + <> + + <Trans>Select destination instance</Trans> + + + + ; +} diff --git a/src/frontend/src/components/items/LanguageToggle.tsx b/src/frontend/src/components/items/LanguageToggle.tsx new file mode 100644 index 0000000000..4c28415057 --- /dev/null +++ b/src/frontend/src/components/items/LanguageToggle.tsx @@ -0,0 +1,29 @@ +import { ActionIcon, Group } from '@mantine/core'; +import { useDisclosure } from '@mantine/hooks'; +import { IconLanguage } from '@tabler/icons-react'; + +import { LanguageSelect } from './LanguageSelect'; + +export function LanguageToggle() { + const [open, toggle] = useDisclosure(); + + return ( + + toggle.toggle()} size="lg"> + + + {open && ( + + + + )} + + ); +} diff --git a/src/frontend/src/components/nav/Header.tsx b/src/frontend/src/components/nav/Header.tsx index 3fc014e9db..0e3fe7fcb9 100644 --- a/src/frontend/src/components/nav/Header.tsx +++ b/src/frontend/src/components/nav/Header.tsx @@ -4,7 +4,6 @@ import { useNavigate, useParams } from 'react-router-dom'; import { navTabs as mainNavTabs } from '../../defaults/links'; import { InvenTreeStyle } from '../../globalStyle'; -import { ColorToggle } from '../items/ColorToggle'; import { ScanButton } from '../items/ScanButton'; import { MainMenu } from './MainMenu'; import { NavHoverMenu } from './NavHoverMenu'; @@ -25,7 +24,6 @@ export function Header() { - diff --git a/src/frontend/src/components/nav/MainMenu.tsx b/src/frontend/src/components/nav/MainMenu.tsx index a8898508f4..d116b32a46 100644 --- a/src/frontend/src/components/nav/MainMenu.tsx +++ b/src/frontend/src/components/nav/MainMenu.tsx @@ -3,35 +3,20 @@ import { Group, Menu, Skeleton, Text, UnstyledButton } from '@mantine/core'; import { IconChevronDown, IconHeart, - IconLanguage, IconLogout, IconSettings, IconUserCircle } from '@tabler/icons-react'; import { Link } from 'react-router-dom'; -import { languages } from '../../contexts/LanguageContext'; import { doClassicLogout } from '../../functions/auth'; import { InvenTreeStyle } from '../../globalStyle'; import { useApiState } from '../../states/ApiState'; -import { useLocalState } from '../../states/LocalState'; import { PlaceholderPill } from '../items/Placeholder'; export function MainMenu() { const { classes, theme } = InvenTreeStyle(); const [username] = useApiState((state) => [state.user?.name]); - const [locale] = useLocalState((state) => [state.language]); - - // Language - function switchLanguage() { - useLocalState.setState({ - language: languages[(languages.indexOf(locale) + 1) % languages.length] - }); - } - function enablePsuedo() { - useLocalState.setState({ language: 'pseudo-LOCALE' }); - } - return ( @@ -53,26 +38,15 @@ export function MainMenu() { Notifications - } - component={Link} - to="/profile/user" - > - Profile + }> + Profile Settings - } onClick={switchLanguage}> - Current language {locale} - - } onClick={enablePsuedo}> - Switch to pseudo language - - }> + } component={Link} to="/profile/user"> Account settings - } diff --git a/src/frontend/src/pages/Auth/Login.tsx b/src/frontend/src/pages/Auth/Login.tsx index d15d88843a..42fdb79a92 100644 --- a/src/frontend/src/pages/Auth/Login.tsx +++ b/src/frontend/src/pages/Auth/Login.tsx @@ -1,14 +1,13 @@ -import { Trans, t } from '@lingui/macro'; -import { Center, Container, Group, Select, Stack, Text } from '@mantine/core'; +import { t } from '@lingui/macro'; +import { Center, Container } from '@mantine/core'; import { useToggle } from '@mantine/hooks'; import { useEffect } from 'react'; +import { AuthFormOptions } from '../../components/forms/AuthFormOptions'; import { AuthenticationForm } from '../../components/forms/AuthenticationForm'; -import { HostOptionsForm } from '../../components/forms/HostOptionsForm'; -import { EditButton } from '../../components/items/EditButton'; +import { InstanceOptions } from '../../components/forms/InstanceOptions'; import { defaultHostKey } from '../../defaults/defaultHostList'; import { useLocalState } from '../../states/LocalState'; -import { HostList } from '../../states/states'; export default function Login() { const [hostKey, setHost, hostList] = useLocalState((state) => [ @@ -19,24 +18,12 @@ export default function Login() { const hostname = hostList[hostKey] === undefined ? t`No selection` : hostList[hostKey].name; const [hostEdit, setHostEdit] = useToggle([false, true] as const); - const hostListData = Object.keys(hostList).map((key) => ({ - value: key, - label: hostList[key].name - })); - const [HostListEdit, setHostListEdit] = useToggle([false, true] as const); // Data manipulation functions function ChangeHost(newHost: string): void { setHost(hostList[newHost].host, newHost); - setHostEdit(false); - } - function SaveOptions(newHostList: HostList): void { - useLocalState.setState({ hostList: newHostList }); - if (newHostList[hostKey] === undefined) { - setHost('', ''); - } - setHostListEdit(); } + // Set default host to localhost if no host is selected useEffect(() => { if (hostKey === '') { @@ -44,87 +31,23 @@ export default function Login() { } }, []); + // Main rendering block return (
- - - {!HostListEdit && ( - - } - /> - )} - + ) : ( + <> + + + + )}
); } - -const SelectHost = ({ - hostKey, - ChangeHost, - hostListData, - HostListEdit, - hostEdit, - setHostListEdit -}: { - hostKey: string; - ChangeHost: (newHost: string) => void; - hostListData: any; - HostListEdit: boolean; - hostEdit: boolean; - setHostListEdit: (value?: React.SetStateAction | undefined) => void; -}) => { - if (!hostEdit) return <>; - return ( - -