Working on new update indicator
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
export const REPO_URL = 'ajnart/homarr';
|
export const REPO_URL = 'ajnart/homarr';
|
||||||
export const CURRENT_VERSION = 'v0.10.7';
|
export const CURRENT_VERSION = 'v0.10.6';
|
||||||
|
|||||||
@@ -1,39 +1,80 @@
|
|||||||
import { ActionIcon, Title, Tooltip, Drawer, Tabs, ScrollArea } from '@mantine/core';
|
import {
|
||||||
import { useHotkeys } from '@mantine/hooks';
|
ActionIcon,
|
||||||
import { useState } from 'react';
|
Title,
|
||||||
import { IconSettings } from '@tabler/icons';
|
Tooltip,
|
||||||
|
Drawer,
|
||||||
|
Tabs,
|
||||||
|
ScrollArea,
|
||||||
|
Indicator,
|
||||||
|
Alert,
|
||||||
|
Notification,
|
||||||
|
} from '@mantine/core';
|
||||||
|
import { useElementSize, useHotkeys, useViewportSize } from '@mantine/hooks';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { IconInfoCircle, IconSettings } from '@tabler/icons';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
import AdvancedSettings from './AdvancedSettings';
|
import AdvancedSettings from './AdvancedSettings';
|
||||||
import CommonSettings from './CommonSettings';
|
import CommonSettings from './CommonSettings';
|
||||||
import Credits from './Credits';
|
import Credits from './Credits';
|
||||||
|
import { CURRENT_VERSION, REPO_URL } from '../../../data/constants';
|
||||||
|
|
||||||
function SettingsMenu(props: any) {
|
function SettingsMenu({ newVersionAvailable }: { newVersionAvailable: string }) {
|
||||||
const { t } = useTranslation('settings/common');
|
const { t } = useTranslation('settings/common');
|
||||||
|
const { height, width } = useViewportSize();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs defaultValue="Common">
|
<>
|
||||||
<Tabs.List grow>
|
<Notification
|
||||||
<Tabs.Tab value="Common">{t('tabs.common')}</Tabs.Tab>
|
icon={<IconInfoCircle size={25} />}
|
||||||
<Tabs.Tab value="Customizations">{t('tabs.customizations')}</Tabs.Tab>
|
disallowClose
|
||||||
</Tabs.List>
|
color="teal"
|
||||||
<Tabs.Panel data-autofocus value="Common">
|
radius="md"
|
||||||
<ScrollArea style={{ height: '78vh' }} offsetScrollbars>
|
title="New update available"
|
||||||
<CommonSettings />
|
hidden={newVersionAvailable === ''}
|
||||||
</ScrollArea>
|
>
|
||||||
</Tabs.Panel>
|
{
|
||||||
<Tabs.Panel value="Customizations">
|
//TODO: Translate and add link to release page}
|
||||||
<ScrollArea style={{ height: '78vh' }} offsetScrollbars>
|
}
|
||||||
<AdvancedSettings />
|
Version <b>{newVersionAvailable}</b> is available, update now!
|
||||||
</ScrollArea>
|
</Notification>
|
||||||
</Tabs.Panel>
|
|
||||||
</Tabs>
|
<Tabs defaultValue="Common">
|
||||||
|
<Tabs.List grow>
|
||||||
|
<Tabs.Tab value="Common">{t('tabs.common')}</Tabs.Tab>
|
||||||
|
<Tabs.Tab value="Customizations">{t('tabs.customizations')}</Tabs.Tab>
|
||||||
|
</Tabs.List>
|
||||||
|
<Tabs.Panel data-autofocus value="Common">
|
||||||
|
<ScrollArea style={{ height: height - 100 }} offsetScrollbars>
|
||||||
|
<CommonSettings />
|
||||||
|
<Credits />
|
||||||
|
</ScrollArea>
|
||||||
|
</Tabs.Panel>
|
||||||
|
<Tabs.Panel value="Customizations">
|
||||||
|
<ScrollArea style={{ height: height - 120 }} offsetScrollbars>
|
||||||
|
<AdvancedSettings />
|
||||||
|
<Credits />
|
||||||
|
</ScrollArea>
|
||||||
|
</Tabs.Panel>
|
||||||
|
</Tabs>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SettingsMenuButton(props: any) {
|
export function SettingsMenuButton(props: any) {
|
||||||
useHotkeys([['ctrl+L', () => setOpened(!opened)]]);
|
useHotkeys([['ctrl+L', () => setOpened(!opened)]]);
|
||||||
const { t } = useTranslation('settings/common');
|
const { t } = useTranslation('settings/common');
|
||||||
|
const [newVersionAvailable, setNewVersionAvailable] = useState<string>('');
|
||||||
|
useEffect(() => {
|
||||||
|
// Fetch Data here when component first mounted
|
||||||
|
fetch(`https://api.github.com/repos/${REPO_URL}/releases/latest`).then((res) => {
|
||||||
|
res.json().then((data) => {
|
||||||
|
if (data.tag_name > CURRENT_VERSION) {
|
||||||
|
setNewVersionAvailable(data.tag_name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, [CURRENT_VERSION]);
|
||||||
|
|
||||||
const [opened, setOpened] = useState(false);
|
const [opened, setOpened] = useState(false);
|
||||||
|
|
||||||
@@ -47,20 +88,21 @@ export function SettingsMenuButton(props: any) {
|
|||||||
opened={props.opened || opened}
|
opened={props.opened || opened}
|
||||||
onClose={() => setOpened(false)}
|
onClose={() => setOpened(false)}
|
||||||
>
|
>
|
||||||
<SettingsMenu />
|
<SettingsMenu newVersionAvailable={newVersionAvailable} />
|
||||||
<Credits />
|
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<Tooltip label={t('tooltip')}>
|
<Tooltip label={t('tooltip')}>
|
||||||
<ActionIcon
|
<Indicator size={15} color="blue" withBorder processing disabled={!newVersionAvailable}>
|
||||||
variant="default"
|
<ActionIcon
|
||||||
radius="md"
|
variant="default"
|
||||||
size="xl"
|
radius="md"
|
||||||
color="blue"
|
size="xl"
|
||||||
style={props.style}
|
color="blue"
|
||||||
onClick={() => setOpened(true)}
|
style={props.style}
|
||||||
>
|
onClick={() => setOpened(true)}
|
||||||
<IconSettings />
|
>
|
||||||
</ActionIcon>
|
<IconSettings />
|
||||||
|
</ActionIcon>
|
||||||
|
</Indicator>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
import { createStyles, Footer as FooterComponent } from '@mantine/core';
|
|
||||||
import { showNotification } from '@mantine/notifications';
|
|
||||||
import { IconAlertCircle as AlertCircle } from '@tabler/icons';
|
|
||||||
import { CURRENT_VERSION, REPO_URL } from '../../../data/constants';
|
|
||||||
|
|
||||||
const useStyles = createStyles((theme) => ({
|
|
||||||
footer: {
|
|
||||||
borderTop: `1px solid ${
|
|
||||||
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2]
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
|
|
||||||
inner: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'center',
|
|
||||||
padding: `${theme.spacing.md}px ${theme.spacing.md}px`,
|
|
||||||
|
|
||||||
[theme.fn.smallerThan('sm')]: {
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
links: {
|
|
||||||
[theme.fn.smallerThan('sm')]: {
|
|
||||||
marginTop: theme.spacing.lg,
|
|
||||||
marginBottom: theme.spacing.sm,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
interface FooterCenteredProps {
|
|
||||||
links: { link: string; label: string }[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Footer({ links }: FooterCenteredProps) {
|
|
||||||
useEffect(() => {
|
|
||||||
// Fetch Data here when component first mounted
|
|
||||||
fetch(`https://api.github.com/repos/${REPO_URL}/releases/latest`).then((res) => {
|
|
||||||
res.json().then((data) => {
|
|
||||||
if (data.tag_name > CURRENT_VERSION) {
|
|
||||||
showNotification({
|
|
||||||
color: 'yellow',
|
|
||||||
autoClose: false,
|
|
||||||
title: 'New version available',
|
|
||||||
icon: <AlertCircle />,
|
|
||||||
message: `Version ${data.tag_name} is available, update now!`,
|
|
||||||
});
|
|
||||||
} else if (data.tag_name < CURRENT_VERSION) {
|
|
||||||
showNotification({
|
|
||||||
color: 'orange',
|
|
||||||
autoClose: 5000,
|
|
||||||
title: 'You are using a development version',
|
|
||||||
icon: <AlertCircle />,
|
|
||||||
message: 'This version of Homarr is still in development! Bugs are expected 🐛',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FooterComponent
|
|
||||||
height="auto"
|
|
||||||
style={{
|
|
||||||
background: 'none',
|
|
||||||
border: 'none',
|
|
||||||
clear: 'both',
|
|
||||||
}}
|
|
||||||
children={undefined}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { AppShell, createStyles } from '@mantine/core';
|
import { AppShell, createStyles } from '@mantine/core';
|
||||||
import { Header } from './header/Header';
|
import { Header } from './header/Header';
|
||||||
import { Footer } from './Footer';
|
|
||||||
import Aside from './Aside';
|
import Aside from './Aside';
|
||||||
import Navbar from './Navbar';
|
import Navbar from './Navbar';
|
||||||
import { HeaderConfig } from './header/HeaderConfig';
|
import { HeaderConfig } from './header/HeaderConfig';
|
||||||
@@ -30,7 +29,6 @@ export default function Layout({ children, style }: any) {
|
|||||||
header={<Header />}
|
header={<Header />}
|
||||||
navbar={widgetPosition ? <Navbar /> : undefined}
|
navbar={widgetPosition ? <Navbar /> : undefined}
|
||||||
aside={widgetPosition ? undefined : <Aside />}
|
aside={widgetPosition ? undefined : <Aside />}
|
||||||
footer={<Footer links={[]} />}
|
|
||||||
>
|
>
|
||||||
<HeaderConfig />
|
<HeaderConfig />
|
||||||
<Background />
|
<Background />
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ async function Get(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
});
|
});
|
||||||
// Return 200 if the alive property is true
|
// Return 200 if the alive property is true
|
||||||
if (response.alive) {
|
if (response.alive) {
|
||||||
return res.status(200).end();
|
return res.status(200).json({ alive: true });
|
||||||
}
|
}
|
||||||
// Return 404 if the alive property is false
|
// Return 404 if the alive property is false
|
||||||
return res.status(404).end();
|
return res.status(404).json({ alive: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user