Open tabs in batch (#1006)

This commit is contained in:
Manuel
2023-06-07 21:44:44 +02:00
committed by GitHub
parent 7cb094e127
commit cee5911259
6 changed files with 368 additions and 361 deletions

View File

@@ -0,0 +1,18 @@
{
"modals": {
"blockedPopups": {
"title": "Popups blocked",
"text": "Your browser has blocked Homarr from accessing it's API. This is most commonly caused by AdBlockers or denied permissions. Homarr is unable to request permissions automatically.",
"list": {
"browserPermission": "Click on the icon besides the URL and check the permisions. Allow Popups and windows",
"adBlockers": "Disable ad blockers and security tools from your browser",
"otherBrowser": "Try a different browser"
}
}
},
"actions": {
"category": {
"openAllInNewTab": "Open all in new tab"
}
}
}

View File

@@ -1,5 +1,5 @@
import { ActionIcon, Menu } from '@mantine/core'; import { ActionIcon, Menu } from '@mantine/core';
import { IconDots, IconLayoutKanban, IconPencil, IconTrash } from '@tabler/icons-react'; import { IconLayoutKanban, IconPencil, IconSettings, IconTrash } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useEditModeStore } from '../Views/useEditModeStore'; import { useEditModeStore } from '../Views/useEditModeStore';
@@ -35,7 +35,7 @@ export const GenericTileMenu = ({
right={8} right={8}
style={{ zIndex: 1 }} style={{ zIndex: 1 }}
> >
<IconDots /> <IconSettings />
</ActionIcon> </ActionIcon>
</Menu.Target> </Menu.Target>
<Menu.Dropdown w={250}> <Menu.Dropdown w={250}>

View File

@@ -1,5 +1,18 @@
import { Accordion, Title } from '@mantine/core'; import {
Accordion,
ActionIcon,
Box,
Menu,
Title,
Text,
Stack,
List,
createStyles,
} from '@mantine/core';
import { useLocalStorage } from '@mantine/hooks'; import { useLocalStorage } from '@mantine/hooks';
import { IconDotsVertical, IconShare3 } from '@tabler/icons-react';
import { modals } from '@mantine/modals';
import { useTranslation } from 'next-i18next';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
import { CategoryType } from '../../../../types/category'; import { CategoryType } from '../../../../types/category';
import { useCardStyles } from '../../../layout/useCardStyles'; import { useCardStyles } from '../../../layout/useCardStyles';
@@ -17,6 +30,8 @@ export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
const isEditMode = useEditModeStore((x) => x.enabled); const isEditMode = useEditModeStore((x) => x.enabled);
const { config } = useConfigContext(); const { config } = useConfigContext();
const { classes: cardClasses, cx } = useCardStyles(true); const { classes: cardClasses, cx } = useCardStyles(true);
const { classes } = useStyles();
const { t } = useTranslation(['layout/common', 'common']);
const categoryList = config?.categories.map((x) => x.name) ?? []; const categoryList = config?.categories.map((x) => x.name) ?? [];
const [toggledCategories, setToggledCategories] = useLocalStorage({ const [toggledCategories, setToggledCategories] = useLocalStorage({
@@ -25,6 +40,44 @@ export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
defaultValue: categoryList, defaultValue: categoryList,
}); });
const handleMenuClick = () => {
for (let i = 0; i < apps.length; i += 1) {
const app = apps[i];
const popUp = window.open(app.url, app.id);
if (popUp === null) {
modals.openConfirmModal({
title: <Text weight="bold">{t('modals.blockedPopups.title')}</Text>,
children: (
<Stack maw="100%">
<Text>{t('modals.blockedPopups.text')}</Text>
<List>
<List.Item className={classes.listItem}>
{t('modals.blockedPopups.list.browserPermission')}
</List.Item>
<List.Item className={classes.listItem}>
{t('modals.blockedPopups.list.adBlockers')}
</List.Item>
<List.Item className={classes.listItem}>
{t('modals.blockedPopups.list.otherBrowser')}
</List.Item>
</List>
</Stack>
),
labels: {
confirm: t('common:close'),
cancel: '',
},
cancelProps: {
display: 'none',
},
closeOnClickOutside: false,
});
break;
}
}
};
return ( return (
<Accordion <Accordion
classNames={{ classNames={{
@@ -43,9 +96,28 @@ export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
}} }}
> >
<Accordion.Item value={category.name}> <Accordion.Item value={category.name}>
<Accordion.Control icon={isEditMode && <CategoryEditMenu category={category} />}> <Box sx={{ display: 'flex', alignItems: 'center' }}>
<Title order={3}>{category.name}</Title> <Accordion.Control icon={isEditMode && <CategoryEditMenu category={category} />}>
</Accordion.Control> <Title order={3}>{category.name}</Title>
</Accordion.Control>
{!isEditMode && (
<Menu withArrow withinPortal>
<Menu.Target>
<ActionIcon variant="light" mr="md">
<IconDotsVertical />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
onClick={handleMenuClick}
icon={<IconShare3 size="1rem" />}
>
{t('actions.category.openAllInNewTab')}
</Menu.Item>
</Menu.Dropdown>
</Menu>
)}
</Box>
<Accordion.Panel> <Accordion.Panel>
<div <div
className="grid-stack grid-stack-category" className="grid-stack grid-stack-category"
@@ -59,3 +131,11 @@ export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
</Accordion> </Accordion>
); );
}; };
const useStyles = createStyles(() => ({
listItem: {
'& div': {
maxWidth: 'calc(100% - 23px)',
},
},
}));

View File

@@ -1,12 +1,12 @@
import { ActionIcon, Menu } from '@mantine/core'; import { ActionIcon, Menu } from '@mantine/core';
import { import {
IconDots,
IconTransitionTop, IconTransitionTop,
IconTransitionBottom, IconTransitionBottom,
IconRowInsertTop, IconRowInsertTop,
IconRowInsertBottom, IconRowInsertBottom,
IconEdit, IconEdit,
IconTrash, IconTrash,
IconSettings,
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
import { CategoryType } from '../../../../types/category'; import { CategoryType } from '../../../../types/category';
@@ -25,7 +25,7 @@ export const CategoryEditMenu = ({ category }: CategoryEditMenuProps) => {
<Menu withinPortal withArrow> <Menu withinPortal withArrow>
<Menu.Target> <Menu.Target>
<ActionIcon> <ActionIcon>
<IconDots /> <IconSettings />
</ActionIcon> </ActionIcon>
</Menu.Target> </Menu.Target>
<Menu.Dropdown> <Menu.Dropdown>

View File

@@ -4,6 +4,7 @@ export const dashboardNamespaces = [
'layout/modals/add-app', 'layout/modals/add-app',
'layout/modals/change-position', 'layout/modals/change-position',
'layout/modals/about', 'layout/modals/about',
'layout/common',
'layout/header/actions/toggle-edit-mode', 'layout/header/actions/toggle-edit-mode',
'layout/mobile/drawer', 'layout/mobile/drawer',
'settings/common', 'settings/common',

614
yarn.lock

File diff suppressed because it is too large Load Diff