Add the status indicator for new versions

This commit is contained in:
ajnart
2022-12-20 15:21:36 +09:00
parent 11b111209a
commit 9996ff1529
4 changed files with 89 additions and 17 deletions

View File

@@ -1,9 +1,11 @@
import {
ActionIcon,
Anchor,
Badge,
Button,
createStyles,
Group,
HoverCard,
Modal,
Table,
Text,
@@ -17,6 +19,7 @@ import {
IconVocabulary,
IconWorldWww,
} from '@tabler/icons';
import { motion } from 'framer-motion';
import { InitOptions } from 'i18next';
import { i18n } from 'next-i18next';
import Image from 'next/image';
@@ -27,12 +30,13 @@ import { usePrimaryGradient } from '../layout/useGradient';
interface AboutModalProps {
opened: boolean;
closeModal: () => void;
newVersionAvailable?: string;
}
export const AboutModal = ({ opened, closeModal }: AboutModalProps) => {
export const AboutModal = ({ opened, closeModal, newVersionAvailable }: AboutModalProps) => {
const { classes } = useStyles();
const colorGradiant = usePrimaryGradient();
const informations = useInformationTableItems();
const informations = useInformationTableItems(newVersionAvailable);
return (
<Modal
@@ -123,7 +127,8 @@ interface ExtendedInitOptions extends InitOptions {
locales: string[];
}
const useInformationTableItems = (): InformationTableItem[] => {
const useInformationTableItems = (newVersionAvailable?: string): InformationTableItem[] => {
// TODO: Fix this to not request. Pass it as a prop.
const colorGradiant = usePrimaryGradient();
let items: InformationTableItem[] = [];
@@ -161,9 +166,41 @@ const useInformationTableItems = (): InformationTableItem[] => {
icon: <IconVersions size={20} />,
label: 'Homarr version',
content: (
<Badge variant="gradient" gradient={colorGradiant}>
{CURRENT_VERSION}
</Badge>
<Group position="right">
<Badge variant="gradient" gradient={colorGradiant}>
{CURRENT_VERSION}
</Badge>
{newVersionAvailable && (
<HoverCard shadow="md" position="top" withArrow>
<HoverCard.Target>
<motion.div
initial={{ scale: 1.2 }}
animate={{
scale: [0.8, 1.10, 1],
rotate: [0, 10, 0],
}}
transition={{ duration: 0.8, ease: 'easeInOut' }}
>
<Badge color="green" variant="filled">
new: {newVersionAvailable}
</Badge>
</motion.div>
</HoverCard.Target>
<HoverCard.Dropdown>
Version{' '}
<b>
<Anchor
target="_blank"
href={`https://github.com/ajnart/homarr/releases/tag/${newVersionAvailable}`}
>
{newVersionAvailable}
</Anchor>
</b>{' '}
is available ! Current version: {CURRENT_VERSION}
</HoverCard.Dropdown>
</HoverCard>
)}
</Group>
),
},
];

View File

@@ -5,7 +5,7 @@ import CustomizationSettings from './Customization/CustomizationSettings';
import CommonSettings from './Common/CommonSettings';
import Credits from './Common/Credits';
function SettingsMenu() {
function SettingsMenu({ newVersionAvailable }: { newVersionAvailable: string }) {
const { t } = useTranslation('settings/common');
return (
@@ -33,7 +33,11 @@ interface SettingsDrawerProps {
closeDrawer: () => void;
}
export function SettingsDrawer({ opened, closeDrawer }: SettingsDrawerProps) {
export function SettingsDrawer({
opened,
closeDrawer,
newVersionAvailable,
}: SettingsDrawerProps & { newVersionAvailable: string }) {
const { t } = useTranslation('settings/common');
return (
@@ -45,7 +49,7 @@ export function SettingsDrawer({ opened, closeDrawer }: SettingsDrawerProps) {
opened={opened}
onClose={closeDrawer}
>
<SettingsMenu />
<SettingsMenu newVersionAvailable={newVersionAvailable} />
<Credits />
</Drawer>
);

View File

@@ -1,4 +1,6 @@
import { Box, createStyles, Group, Header as MantineHeader } from '@mantine/core';
import { Box, createStyles, Group, Header as MantineHeader, Indicator } from '@mantine/core';
import { useState, useEffect } from 'react';
import { REPO_URL, CURRENT_VERSION } from '../../../../data/constants';
import { useConfigContext } from '../../../config/provider';
import { Logo } from '../Logo';
import { useCardStyles } from '../useCardStyles';
@@ -15,6 +17,18 @@ export function Header(props: any) {
const { config } = useConfigContext();
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]);
return (
<MantineHeader height={HeaderHeight} className={cardClasses.card}>
<Group p="xs" noWrap grow>
@@ -25,7 +39,9 @@ export function Header(props: any) {
<Search />
<AddElementAction />
<ToggleEditModeAction />
<SettingsMenu />
<Indicator size={15} color="blue" withBorder processing disabled={!newVersionAvailable}>
<SettingsMenu newVersionAvailable={newVersionAvailable} />
</Indicator>
</Group>
</Group>
</MantineHeader>

View File

@@ -1,4 +1,4 @@
import { ActionIcon, Menu, Tooltip } from '@mantine/core';
import { ActionIcon, Badge, Menu, Tooltip } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { IconInfoCircle, IconMenu2, IconSettings } from '@tabler/icons';
import { useTranslation } from 'next-i18next';
@@ -6,7 +6,7 @@ import { AboutModal } from '../../About/AboutModal';
import { SettingsDrawer } from '../../Settings/SettingsDrawer';
import { ColorSchemeSwitch } from './SettingsMenu/ColorSchemeSwitch';
export const SettingsMenu = () => {
export function SettingsMenu({ newVersionAvailable }: { newVersionAvailable: string }) {
const [drawerOpened, drawer] = useDisclosure(false);
const { t } = useTranslation('common');
const [aboutModalOpened, aboutModal] = useDisclosure(false);
@@ -28,15 +28,30 @@ export const SettingsMenu = () => {
</Menu.Item>
<Menu.Item
icon={<IconInfoCircle strokeWidth={1.2} size={18} />}
onClick={aboutModal.open}
rightSection={
newVersionAvailable && (
<Badge variant="light" color="blue">
New
</Badge>
)
}
onClick={() => aboutModal.open()}
>
About
</Menu.Item>
</Menu.Dropdown>
</Menu>
</Tooltip>
<SettingsDrawer opened={drawerOpened} closeDrawer={drawer.close} />
<AboutModal opened={aboutModalOpened} closeModal={aboutModal.close} />
<SettingsDrawer
opened={drawerOpened}
closeDrawer={drawer.close}
newVersionAvailable={newVersionAvailable}
/>
<AboutModal
opened={aboutModalOpened}
closeModal={aboutModal.close}
newVersionAvailable={newVersionAvailable}
/>
</>
);
};
}