mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-11 16:05:47 +01:00
🐛 Fix Accordion in AppShelf
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Accordion, createStyles, Grid, Group, Paper, Stack, useMantineColorScheme } from '@mantine/core';
|
import { Accordion, Grid, Paper, Stack, useMantineColorScheme } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
closestCenter,
|
closestCenter,
|
||||||
DndContext,
|
DndContext,
|
||||||
@@ -18,44 +18,22 @@ import { ModuleMenu, ModuleWrapper } from '../../modules/moduleWrapper';
|
|||||||
import { DownloadsModule } from '../../modules';
|
import { DownloadsModule } from '../../modules';
|
||||||
import DownloadComponent from '../../modules/downloads/DownloadsModule';
|
import DownloadComponent from '../../modules/downloads/DownloadsModule';
|
||||||
|
|
||||||
const useStyles = createStyles((theme, _params) => ({
|
|
||||||
item: {
|
|
||||||
overflow: 'hidden',
|
|
||||||
borderLeft: '3px solid transparent',
|
|
||||||
borderRight: '3px solid transparent',
|
|
||||||
borderBottom: '3px solid transparent',
|
|
||||||
borderRadius: '20px',
|
|
||||||
borderColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1],
|
|
||||||
marginTop: theme.spacing.md,
|
|
||||||
},
|
|
||||||
|
|
||||||
control: {
|
|
||||||
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1],
|
|
||||||
borderRadius: theme.spacing.md,
|
|
||||||
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
content: {
|
|
||||||
margin: theme.spacing.md,
|
|
||||||
},
|
|
||||||
|
|
||||||
label: {
|
|
||||||
overflow: 'visible',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const AppShelf = (props: any) => {
|
const AppShelf = (props: any) => {
|
||||||
const { classes, cx } = useStyles(props);
|
const { config, setConfig } = useConfig();
|
||||||
const [toggledCategories, settoggledCategories] = useLocalStorage({
|
// Extract all the categories from the services in config
|
||||||
|
const categoryList = config.services.reduce((acc, cur) => {
|
||||||
|
if (cur.category && !acc.includes(cur.category)) {
|
||||||
|
acc.push(cur.category);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, [] as string[]);
|
||||||
|
|
||||||
|
const [toggledCategories, setToggledCategories] = useLocalStorage({
|
||||||
key: 'app-shelf-toggled',
|
key: 'app-shelf-toggled',
|
||||||
// This is a bit of a hack to get the 5 first categories to be toggled on by default
|
// This is a bit of a hack to toggle the categories on the first load, return a string[] of the categories
|
||||||
defaultValue: { 0: true, 1: true, 2: true, 3: true, 4: true } as Record<string, boolean>,
|
defaultValue: categoryList,
|
||||||
});
|
});
|
||||||
const [activeId, setActiveId] = useState(null);
|
const [activeId, setActiveId] = useState(null);
|
||||||
const { config, setConfig } = useConfig();
|
|
||||||
const { colorScheme } = useMantineColorScheme();
|
const { colorScheme } = useMantineColorScheme();
|
||||||
|
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
@@ -93,15 +71,8 @@ const AppShelf = (props: any) => {
|
|||||||
|
|
||||||
setActiveId(null);
|
setActiveId(null);
|
||||||
}
|
}
|
||||||
// Extract all the categories from the services in config
|
|
||||||
const categoryList = config.services.reduce((acc, cur) => {
|
|
||||||
if (cur.category && !acc.includes(cur.category)) {
|
|
||||||
acc.push(cur.category);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, [] as string[]);
|
|
||||||
|
|
||||||
const item = (filter?: string) => {
|
const getItems = (filter?: string) => {
|
||||||
// If filter is not set, return all the services without a category or a null category
|
// If filter is not set, return all the services without a category or a null category
|
||||||
let filtered = config.services;
|
let filtered = config.services;
|
||||||
if (!filter) {
|
if (!filter) {
|
||||||
@@ -155,43 +126,51 @@ const AppShelf = (props: any) => {
|
|||||||
const downloadEnabled = config.modules?.[DownloadsModule.title]?.enabled ?? false;
|
const downloadEnabled = config.modules?.[DownloadsModule.title]?.enabled ?? false;
|
||||||
// Create an item with 0: true, 1: true, 2: true... For each category
|
// Create an item with 0: true, 1: true, 2: true... For each category
|
||||||
return (
|
return (
|
||||||
// Return one item for each category
|
// TODO: Style accordion so that the bar is transparent to the user settings
|
||||||
<Stack>
|
<Stack>
|
||||||
<Accordion
|
<Accordion
|
||||||
disableIconRotation
|
variant="separated"
|
||||||
classNames={classes}
|
radius="lg"
|
||||||
order={2}
|
order={2}
|
||||||
iconPosition="right"
|
|
||||||
multiple
|
multiple
|
||||||
initialState={toggledCategories}
|
value={toggledCategories}
|
||||||
onChange={(idx) => settoggledCategories(idx)}
|
onChange={(state) => {
|
||||||
|
setToggledCategories(state);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{categoryList.map((category, idx) => (
|
{categoryList.map((category, idx) => (
|
||||||
<Accordion.Item key={category} label={category}>
|
<Accordion.Item key={category} value={idx.toString()}>
|
||||||
{item(category)}
|
<Accordion.Control>{category}</Accordion.Control>
|
||||||
|
<Accordion.Panel>{getItems(category)}</Accordion.Panel>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
))}
|
))}
|
||||||
{/* Return the item for all services without category */}
|
{/* Return the item for all services without category */}
|
||||||
{noCategory && noCategory.length > 0 ? (
|
{noCategory && noCategory.length > 0 ? (
|
||||||
<Accordion.Item key="Other" label="Other">
|
<Accordion.Item key="Other" value="Other">
|
||||||
{item()}
|
<Accordion.Control>Other</Accordion.Control>
|
||||||
|
<Accordion.Panel>{getItems()}</Accordion.Panel>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
) : null}
|
) : null}
|
||||||
{downloadEnabled ? (
|
{downloadEnabled ? (
|
||||||
<Accordion.Item key="Downloads" label="Your downloads">
|
<Accordion.Item key="Downloads" value="Your downloads">
|
||||||
|
<Accordion.Control>Your downloads</Accordion.Control>
|
||||||
|
<Accordion.Panel>
|
||||||
<Paper
|
<Paper
|
||||||
p="lg"
|
p="lg"
|
||||||
radius="lg"
|
radius="lg"
|
||||||
style={{
|
style={{
|
||||||
background: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '255, 255, 255,'} \
|
background: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '255, 255, 255,'} \
|
||||||
${(config.settings.appOpacity || 100) / 100}`,
|
${(config.settings.appOpacity || 100) / 100}`,
|
||||||
borderColor: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '233, 236, 239,'} \
|
borderColor: `rgba(${
|
||||||
|
colorScheme === 'dark' ? '37, 38, 43,' : '233, 236, 239,'
|
||||||
|
} \
|
||||||
${(config.settings.appOpacity || 100) / 100}`,
|
${(config.settings.appOpacity || 100) / 100}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ModuleMenu module={DownloadsModule} />
|
<ModuleMenu module={DownloadsModule} />
|
||||||
<DownloadComponent />
|
<DownloadComponent />
|
||||||
</Paper>
|
</Paper>
|
||||||
|
</Accordion.Panel>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
) : null}
|
) : null}
|
||||||
</Accordion>
|
</Accordion>
|
||||||
@@ -200,7 +179,7 @@ const AppShelf = (props: any) => {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
{item()}
|
{getItems()}
|
||||||
<ModuleWrapper mt="xl" module={DownloadsModule} />
|
<ModuleWrapper mt="xl" module={DownloadsModule} />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user