[enhancement]: add server menu on Navidrome error page
This commit is contained in:
parent
e0e967385f
commit
44fcc33825
3 changed files with 32 additions and 4 deletions
|
@ -1,6 +1,6 @@
|
||||||
import { Center, Group, Stack } from '@mantine/core';
|
import { Center, Group, Stack } from '@mantine/core';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { RiCheckFill } from 'react-icons/ri';
|
import { RiCheckFill, RiEdit2Line, RiHome4Line } from 'react-icons/ri';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Button, PageHeader, Text } from '/@/renderer/components';
|
import { Button, PageHeader, Text } from '/@/renderer/components';
|
||||||
import { ActionRequiredContainer } from '/@/renderer/features/action-required/components/action-required-container';
|
import { ActionRequiredContainer } from '/@/renderer/features/action-required/components/action-required-container';
|
||||||
|
@ -9,6 +9,8 @@ import { ServerRequired } from '/@/renderer/features/action-required/components/
|
||||||
import { AnimatedPage } from '/@/renderer/features/shared';
|
import { AnimatedPage } from '/@/renderer/features/shared';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
|
import { openModal } from '@mantine/modals';
|
||||||
|
import { ServerList } from '/@/renderer/features/servers';
|
||||||
|
|
||||||
const ActionRequiredRoute = () => {
|
const ActionRequiredRoute = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -32,6 +34,13 @@ const ActionRequiredRoute = () => {
|
||||||
const canReturnHome = checks.every((c) => c.valid);
|
const canReturnHome = checks.every((c) => c.valid);
|
||||||
const displayedCheck = checks.find((c) => !c.valid);
|
const displayedCheck = checks.find((c) => !c.valid);
|
||||||
|
|
||||||
|
const handleManageServersModal = () => {
|
||||||
|
openModal({
|
||||||
|
children: <ServerList />,
|
||||||
|
title: 'Manage Servers',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatedPage>
|
<AnimatedPage>
|
||||||
<PageHeader />
|
<PageHeader />
|
||||||
|
@ -63,6 +72,7 @@ const ActionRequiredRoute = () => {
|
||||||
<Button
|
<Button
|
||||||
component={Link}
|
component={Link}
|
||||||
disabled={!canReturnHome}
|
disabled={!canReturnHome}
|
||||||
|
leftIcon={<RiHome4Line />}
|
||||||
to={AppRoute.HOME}
|
to={AppRoute.HOME}
|
||||||
variant="filled"
|
variant="filled"
|
||||||
>
|
>
|
||||||
|
@ -70,6 +80,19 @@ const ActionRequiredRoute = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<Group
|
||||||
|
noWrap
|
||||||
|
position="center"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
leftIcon={<RiEdit2Line />}
|
||||||
|
variant="filled"
|
||||||
|
onClick={handleManageServersModal}
|
||||||
|
>
|
||||||
|
{t('page.appMenu.manageServers', { postProcess: 'sentenceCase' })}
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent } from 'react';
|
||||||
import { Divider, Group, Stack } from '@mantine/core';
|
import { Divider, Group, Stack } from '@mantine/core';
|
||||||
import { Accordion, Button, ContextModalVars, Switch } from '/@/renderer/components';
|
import { Accordion, Button, ContextModalVars, Switch, Text } from '/@/renderer/components';
|
||||||
import { useLocalStorage } from '@mantine/hooks';
|
import { useLocalStorage } from '@mantine/hooks';
|
||||||
import { openContextModal } from '@mantine/modals';
|
import { openContextModal } from '@mantine/modals';
|
||||||
import isElectron from 'is-electron';
|
import isElectron from 'is-electron';
|
||||||
|
@ -8,13 +8,14 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { RiAddFill, RiServerFill } from 'react-icons/ri';
|
import { RiAddFill, RiServerFill } from 'react-icons/ri';
|
||||||
import { AddServerForm } from '/@/renderer/features/servers/components/add-server-form';
|
import { AddServerForm } from '/@/renderer/features/servers/components/add-server-form';
|
||||||
import { ServerListItem } from '/@/renderer/features/servers/components/server-list-item';
|
import { ServerListItem } from '/@/renderer/features/servers/components/server-list-item';
|
||||||
import { useServerList } from '/@/renderer/store';
|
import { useCurrentServer, useServerList } from '/@/renderer/store';
|
||||||
import { titleCase } from '/@/renderer/utils';
|
import { titleCase } from '/@/renderer/utils';
|
||||||
|
|
||||||
const localSettings = isElectron() ? window.electron.localSettings : null;
|
const localSettings = isElectron() ? window.electron.localSettings : null;
|
||||||
|
|
||||||
export const ServerList = () => {
|
export const ServerList = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const currentServer = useCurrentServer();
|
||||||
const serverListQuery = useServerList();
|
const serverListQuery = useServerList();
|
||||||
|
|
||||||
const handleAddServerModal = () => {
|
const handleAddServerModal = () => {
|
||||||
|
@ -90,7 +91,9 @@ export const ServerList = () => {
|
||||||
>
|
>
|
||||||
<Accordion.Control icon={<RiServerFill size={15} />}>
|
<Accordion.Control icon={<RiServerFill size={15} />}>
|
||||||
<Group position="apart">
|
<Group position="apart">
|
||||||
{titleCase(server?.type)} - {server?.name}
|
<Text weight={server.id === currentServer?.id ? 800 : 400}>
|
||||||
|
{titleCase(server?.type)} - {server?.name}
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { AuthState, ServerListItem, ServerType } from '/@/renderer/types';
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { SongListSort, SortOrder } from '/@/renderer/api/types';
|
import { SongListSort, SortOrder } from '/@/renderer/api/types';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
import { toast } from '/@/renderer/components';
|
||||||
|
|
||||||
export const useServerAuthenticated = () => {
|
export const useServerAuthenticated = () => {
|
||||||
const priorServerId = useRef<string>();
|
const priorServerId = useRef<string>();
|
||||||
|
@ -29,6 +30,7 @@ export const useServerAuthenticated = () => {
|
||||||
|
|
||||||
setReady(AuthState.VALID);
|
setReady(AuthState.VALID);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
toast.error({ message: (error as Error).message });
|
||||||
setReady(AuthState.INVALID);
|
setReady(AuthState.INVALID);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
Reference in a new issue