🚚 Move all dashboard files in board directory

This commit is contained in:
Meier Lukas
2023-10-09 19:04:18 +02:00
parent fe36cffd19
commit f7fc4315d6
63 changed files with 197 additions and 250 deletions

View File

@@ -0,0 +1,11 @@
import { BoardView } from './BoardView';
import { MobileRibbons } from './Sections/Sidebar/MobileRibbon/MobileRibbon';
export const Board = () => {
return (
<>
<BoardView />
<MobileRibbons />
</>
);
};

View File

@@ -10,10 +10,10 @@ import {
import { useResize } from '~/hooks/use-resize';
import { useScreenLargerThan } from '~/hooks/useScreenLargerThan';
import { BoardCategorySection } from '../../Board/Sections/CategorySection';
import { BoardEmptySection } from '../../Board/Sections/EmptySection';
import { DashboardSidebar } from '../Wrappers/Sidebar/Sidebar';
import { useGridstackStore } from '../Wrappers/gridstack/store';
import { BoardCategorySection } from './Sections/Category/CategorySection';
import { BoardEmptySection } from './Sections/EmptySection';
import { DashboardSidebar } from './Sections/Sidebar/SidebarSection';
import { useGridstackStore } from './gridstack/store';
export const BoardView = () => {
const boardName = useRequiredBoard().name;
@@ -43,6 +43,7 @@ export const BoardView = () => {
visible={!isReady}
transitionDuration={500}
loaderProps={{ size: 'lg', variant: 'bars' }}
h="calc(100dvh - var(--mantine-header-height))"
/>
<Group
align="top"
@@ -51,7 +52,7 @@ export const BoardView = () => {
style={{ visibility: isReady ? 'visible' : 'hidden' }}
>
{sidebarsVisible.left && leftSidebarSection ? (
<DashboardSidebar section={leftSidebarSection} isGridstackReady={isReady} />
<DashboardSidebar section={leftSidebarSection} />
) : null}
<Stack ref={mainAreaRef} mx={-10} style={{ flexGrow: 1 }}>
@@ -70,7 +71,7 @@ export const BoardView = () => {
</Stack>
{sidebarsVisible.right && rightSidebarSection ? (
<DashboardSidebar section={rightSidebarSection} isGridstackReady={isReady} />
<DashboardSidebar section={rightSidebarSection} />
) : null}
</Group>
</Box>

View File

@@ -4,14 +4,14 @@ import { motion } from 'framer-motion';
import Link from 'next/link';
import { AppItem } from '~/components/Board/context';
import { useEditModeStore } from '../../Views/useEditModeStore';
import { HomarrCardWrapper } from '../HomarrCardWrapper';
import { BaseTileProps } from '../type';
import { useEditModeStore } from '../../useEditModeStore';
import { ItemWrapper } from '../ItemWrapper';
import { AppMenu } from './AppMenu';
import { AppPing } from './AppPing';
interface AppTileProps extends BaseTileProps {
interface AppTileProps {
app: AppItem;
className?: string;
}
const namePositions = {
@@ -21,7 +21,7 @@ const namePositions = {
bottom: 'column-reverse',
};
export const AppTile = ({ className, app }: AppTileProps) => {
export const BoardAppItem = ({ className, app }: AppTileProps) => {
const isEditMode = useEditModeStore((x) => x.enabled);
const { cx, classes } = useStyles();
const { colorScheme } = useMantineTheme();
@@ -81,7 +81,7 @@ export const AppTile = ({ className, app }: AppTileProps) => {
const url = app.externalUrl ? app.externalUrl : app.internalUrl;
return (
<HomarrCardWrapper className={className} p={10}>
<ItemWrapper className={className} p={10}>
<AppMenu app={app} />
{!url || isEditMode ? (
<UnstyledButton
@@ -102,11 +102,11 @@ export const AppTile = ({ className, app }: AppTileProps) => {
</UnstyledButton>
)}
<AppPing app={app} />
</HomarrCardWrapper>
</ItemWrapper>
);
};
const useStyles = createStyles((theme, _params, getRef) => ({
const useStyles = createStyles(() => ({
base: {
display: 'flex',
alignItems: 'center',
@@ -133,11 +133,3 @@ const useStyles = createStyles((theme, _params, getRef) => ({
gap: 4,
},
}));
export const appTileDefinition = {
component: AppTile,
minWidth: 1,
minHeight: 1,
maxWidth: 12,
maxHeight: 12,
};

View File

@@ -1,9 +1,9 @@
import { openRemoveItemModal, useItemActions } from '~/components/Board/Items/item-actions';
import { type AppItem, useRequiredBoard } from '~/components/Board/context';
import { useResizeGridItem } from '~/components/Board/gridstack/useResizeGridItem';
import { openRemoveItemModal, useItemActions } from '~/components/Board/item-actions';
import { openContextModalGeneric } from '~/tools/mantineModalManagerExtensions';
import { GenericTileMenu } from '../GenericTileMenu';
import { CommonItemMenu } from '../CommonItemMenu';
interface TileMenuProps {
app: AppItem;
@@ -58,7 +58,7 @@ export const AppMenu = ({ app }: TileMenuProps) => {
};
return (
<GenericTileMenu
<CommonItemMenu
handleClickEdit={handleClickEdit}
handleClickChangePosition={handleClickChangePosition}
handleClickDelete={handleClickDelete}

View File

@@ -1,11 +1,11 @@
import { type SelectItem } from '@mantine/core';
import { type ContextModalProps, closeModal } from '@mantine/modals';
import { useItemActions } from '~/components/Board/Items/item-actions';
import { type AppItem } from '~/components/Board/context';
import { type useResizeGridItem } from '~/components/Board/gridstack/useResizeGridItem';
import { useItemActions } from '~/components/Board/item-actions';
import { useGridstackStore, useWrapperColumnCount } from '../../Wrappers/gridstack/store';
import { ChangePositionModal } from './ChangePositionModal';
import { useGridstackStore, useWrapperColumnCount } from '../../gridstack/store';
import { CommonChangePositionModal } from '../CommonChangePositionModal';
type ChangeAppPositionModalInnerProps = {
app: AppItem;
@@ -40,7 +40,7 @@ export const ChangeAppPositionModal = ({
const heightData = useHeightData();
return (
<ChangePositionModal
<CommonChangePositionModal
onSubmit={handleSubmit}
onCancel={handleCancel}
widthData={widthData}

View File

@@ -2,9 +2,9 @@ import { Stack, Tabs, Text, TextInput } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { IconClick, IconCursorText, IconLink } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { AppType } from '~/types/app';
import { EditAppModalTab } from '../type';
import { EditAppModalTab } from '../EditAppModal';
interface GeneralTabProps {
form: UseFormReturnType<AppType, (values: AppType) => AppType>;
@@ -51,7 +51,7 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => {
<Text color="red" mt="sm" size="sm">
{t('behaviour.customProtocolWarning')}
</Text>
)}
)}
</Stack>
</Tabs.Panel>
);

View File

@@ -2,10 +2,10 @@ import { Alert, Divider, Tabs, Text } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { IconAlertTriangle } from '@tabler/icons-react';
import { Trans, useTranslation } from 'next-i18next';
import { AppType } from '~/types/app';
import { IntegrationSelector } from './Components/InputElements/IntegrationSelector';
import { IntegrationOptionsRenderer } from './Components/IntegrationOptionsRenderer/IntegrationOptionsRenderer';
import { IntegrationSelector } from './InputElements/IntegrationSelector';
import { IntegrationOptionsRenderer } from './IntegrationOptionsRenderer/IntegrationOptionsRenderer';
interface IntegrationTabProps {
form: UseFormReturnType<AppType, (values: AppType) => AppType>;

View File

@@ -12,18 +12,17 @@ import {
} from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { useState } from 'react';
import { useConfigContext } from '~/config/provider';
import { useConfigStore } from '~/config/store';
import { AppType } from '~/types/app';
import { DebouncedImage } from '../../../IconSelector/DebouncedImage';
import { useEditModeStore } from '../../Views/useEditModeStore';
import { AppearanceTab } from './Tabs/AppereanceTab/AppereanceTab';
import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab';
import { GeneralTab } from './Tabs/GeneralTab/GeneralTab';
import { IntegrationTab } from './Tabs/IntegrationTab/IntegrationTab';
import { NetworkTab } from './Tabs/NetworkTab/NetworkTab';
import { EditAppModalTab } from './Tabs/type';
import { useEditModeStore } from '../../useEditModeStore';
import { AppearanceTab } from './Edit/AppereanceTab';
import { BehaviourTab } from './Edit/BehaviourTab';
import { GeneralTab } from './Edit/GeneralTab';
import { IntegrationTab } from './Edit/IntegrationTab/IntegrationTab';
import { NetworkTab } from './Edit/NetworkTab';
const appUrlRegex =
'(https?://(?:www.|(?!www))\\[?[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\]?.[^\\s]{2,}|www.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9].[^\\s]{2,}|https?://(?:www.|(?!www))\\[?[a-zA-Z0-9]+\\]?.[^\\s]{2,}|www.[a-zA-Z0-9]+.[^\\s]{2,})';
@@ -240,3 +239,5 @@ const SaveButton = ({ formIsValid }: { formIsValid: boolean }) => {
</Popover>
);
};
export type EditAppModalTab = 'general' | 'behaviour' | 'network' | 'appereance' | 'integration';

View File

@@ -2,7 +2,7 @@ import { Button, Flex, Grid, NumberInput, Select, SelectItem } from '@mantine/co
import { useForm } from '@mantine/form';
import { useTranslation } from 'next-i18next';
interface ChangePositionModalProps {
interface CommonChangePositionModalProps {
initialX?: number;
initialY?: number;
initialWidth?: number;
@@ -13,7 +13,7 @@ interface ChangePositionModalProps {
onCancel: () => void;
}
export const ChangePositionModal = ({
export const CommonChangePositionModal = ({
initialX,
initialY,
initialWidth,
@@ -22,7 +22,7 @@ export const ChangePositionModal = ({
heightData,
onCancel,
onSubmit,
}: ChangePositionModalProps) => {
}: CommonChangePositionModalProps) => {
const form = useForm<FormType>({
initialValues: {
x: initialX ?? null,

View File

@@ -2,24 +2,21 @@ import { ActionIcon, Menu } from '@mantine/core';
import { IconLayoutKanban, IconPencil, IconSettings, IconTrash } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { useColorTheme } from '~/tools/color';
import { useEditModeStore } from '../Views/useEditModeStore';
import { useEditModeStore } from '../useEditModeStore';
interface GenericTileMenuProps {
interface CommonItemMenuProps {
handleClickEdit: () => void;
handleClickChangePosition: () => void;
handleClickDelete: () => void;
displayEdit: boolean;
}
export const GenericTileMenu = (
{
handleClickEdit,
handleClickChangePosition,
handleClickDelete,
displayEdit,
}: GenericTileMenuProps
) => {
export const CommonItemMenu = ({
handleClickEdit,
handleClickChangePosition,
handleClickDelete,
displayEdit,
}: CommonItemMenuProps) => {
const { t } = useTranslation('common');
const isEditMode = useEditModeStore((x) => x.enabled);

View File

@@ -1,9 +1,9 @@
/* eslint-disable react/no-unknown-property */
import { GridItemHTMLElement } from 'fily-publish-gridstack';
import { ReactNode, RefObject } from 'react';
import { GridItemProvider } from '~/components/Board/item/context';
import { GridItemProvider } from '~/components/Board/Items/context';
interface GridstackTileWrapperProps {
interface GridstackItemWrapperProps {
id: string;
type: 'app' | 'widget';
x?: number;
@@ -18,7 +18,7 @@ interface GridstackTileWrapperProps {
children: ReactNode;
}
export const GridstackTileWrapper = ({
export const GridstackItemWrapper = ({
id,
type,
x,
@@ -31,7 +31,7 @@ export const GridstackTileWrapper = ({
maxHeight,
children,
itemRef,
}: GridstackTileWrapperProps) => {
}: GridstackItemWrapperProps) => {
const locationProperties = useLocationProperties(x, y);
const normalizedWidth = width ?? minWidth;
const normalizedHeight = height ?? minHeight;

View File

@@ -2,19 +2,17 @@ import { Card, CardProps } from '@mantine/core';
import { ReactNode } from 'react';
import { useCardStyles } from '../../layout/Common/useCardStyles';
import { useEditModeStore } from '../Views/useEditModeStore';
import { useEditModeStore } from '../useEditModeStore';
interface HomarrCardWrapperProps extends CardProps {
interface ItemWrapperProps extends CardProps {
children: ReactNode;
isCategory?: boolean;
}
export const HomarrCardWrapper = ({ ...props }: HomarrCardWrapperProps) => {
const { isCategory = false, ...restProps } = props;
export const ItemWrapper = ({ ...restProps }: ItemWrapperProps) => {
const {
cx,
classes: { card: cardClass },
} = useCardStyles(isCategory);
} = useCardStyles(false);
const isEditMode = useEditModeStore((x) => x.enabled);
return (
<Card

View File

@@ -1,12 +1,12 @@
import { type SelectItem } from '@mantine/core';
import { type ContextModalProps, closeModal } from '@mantine/modals';
import { useItemActions } from '~/components/Board/Items/item-actions';
import { type WidgetItem } from '~/components/Board/context';
import { type useResizeGridItem } from '~/components/Board/gridstack/useResizeGridItem';
import { useItemActions } from '~/components/Board/item-actions';
import widgets from '../../../../widgets';
import { useGridstackStore, useWrapperColumnCount } from '../../Wrappers/gridstack/store';
import { ChangePositionModal } from './ChangePositionModal';
import { useGridstackStore, useWrapperColumnCount } from '../../gridstack/store';
import { CommonChangePositionModal } from '../CommonChangePositionModal';
export type WidgetChangePositionModalInnerProps = {
widget: WidgetItem;
@@ -43,7 +43,7 @@ export const ChangeWidgetPositionModal = ({
const heightData = useHeightData(innerProps.widget.sort);
return (
<ChangePositionModal
<CommonChangePositionModal
onSubmit={handleSubmit}
onCancel={handleCancel}
heightData={heightData}

View File

@@ -1,23 +1,22 @@
import { Title } from '@mantine/core';
import { useTranslation } from 'next-i18next';
import { openRemoveItemModal, useItemActions } from '~/components/Board/Items/item-actions';
import { type WidgetItem, useRequiredBoard } from '~/components/Board/context';
import { useResizeGridItem } from '~/components/Board/gridstack/useResizeGridItem';
import { openRemoveItemModal, useItemActions } from '~/components/Board/item-actions';
import { openContextModalGeneric } from '~/tools/mantineModalManagerExtensions';
import WidgetsDefinitions from '../../../../widgets';
import { type WidgetChangePositionModalInnerProps } from '../../Modals/ChangePosition/ChangeWidgetPositionModal';
import { useWrapperColumnCount } from '../../Wrappers/gridstack/store';
import { GenericTileMenu } from '../GenericTileMenu';
import { useWrapperColumnCount } from '../../gridstack/store';
import { CommonItemMenu } from '../CommonItemMenu';
import { type WidgetChangePositionModalInnerProps } from './ChangeWidgetPositionModal';
import { type WidgetEditModalInnerProps } from './WidgetsEditModal';
interface WidgetsMenuProps {
type: string;
widget: WidgetItem | undefined;
widget: WidgetItem;
}
export const WidgetsMenu = ({ type, widget }: WidgetsMenuProps) => {
const { t } = useTranslation(`modules/${type}`);
export const WidgetsMenu = ({ widget }: WidgetsMenuProps) => {
const { t } = useTranslation(`modules/${widget.sort}`);
const board = useRequiredBoard();
const wrapperColumnCount = useWrapperColumnCount();
const resizeGridItem = useResizeGridItem();
@@ -58,7 +57,7 @@ export const WidgetsMenu = ({ type, widget }: WidgetsMenuProps) => {
title: <Title order={4}>{t('descriptor.settings.title')}</Title>,
innerProps: {
widgetId: widget.id,
widgetType: type,
widgetType: widget.sort,
options: widget.options,
boardName: board.name,
widgetOptions: widgetDefinitionObject.options,
@@ -68,7 +67,7 @@ export const WidgetsMenu = ({ type, widget }: WidgetsMenuProps) => {
};
return (
<GenericTileMenu
<CommonItemMenu
handleClickEdit={handleEditClick}
handleClickChangePosition={handleChangeSizeClick}
handleClickDelete={handleDeleteClick}

View File

@@ -14,7 +14,7 @@ import {
} from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { useCallback, useMemo } from 'react';
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useEditModeStore } from '~/components/Board/useEditModeStore';
import { AppItem, CategorySection } from '../../context';
import { useCategoryMenuActions } from './Actions/category-menu-actions';

View File

@@ -4,11 +4,11 @@ import { useTranslation } from 'next-i18next';
import { useCallback, useMemo } from 'react';
import { AppItem, CategorySection } from '~/components/Board/context';
import { useEditModeStore } from '../../Dashboard/Views/useEditModeStore';
import { WrapperContent } from '../../Dashboard/Wrappers/WrapperContent';
import { useGridstack } from '../../Dashboard/Wrappers/gridstack/use-gridstack';
import { useCardStyles } from '../../layout/Common/useCardStyles';
import { CategoryMenu } from './Category/CategoryMenu';
import { useCardStyles } from '../../../layout/Common/useCardStyles';
import { useGridstack } from '../../gridstack/use-gridstack';
import { useEditModeStore } from '../../useEditModeStore';
import { SectionContent } from '../SectionContent';
import { CategoryMenu } from './CategoryMenu';
interface DashboardCategoryProps {
section: CategorySection;
@@ -49,7 +49,7 @@ export const BoardCategorySection = ({ section, isOpened, toggle }: DashboardCat
data-category={section.id}
ref={refs.wrapper}
>
<WrapperContent items={section.items} refs={refs} />
<SectionContent items={section.items} refs={refs} />
</div>
</Accordion.Panel>
</Accordion.Item>

View File

@@ -1,9 +1,9 @@
import { EmptySection } from '~/components/Board/context';
import { GridstackProvider } from '~/components/Board/gridstack/context';
import { useEditModeStore } from '../../Dashboard/Views/useEditModeStore';
import { WrapperContent } from '../../Dashboard/Wrappers/WrapperContent';
import { useGridstack } from '../../Dashboard/Wrappers/gridstack/use-gridstack';
import { useGridstack } from '../gridstack/use-gridstack';
import { useEditModeStore } from '../useEditModeStore';
import { SectionContent } from './SectionContent';
interface EmptySectionWrapperProps {
section: EmptySection;
@@ -28,7 +28,7 @@ export const BoardEmptySection = ({ section }: EmptySectionWrapperProps) => {
ref={refs.wrapper}
>
{section.items.length === 0 && <span></span>}
<WrapperContent items={section.items} refs={refs} />
<SectionContent items={section.items} refs={refs} />
</div>
</GridstackProvider>
);

View File

@@ -1,16 +1,13 @@
import { GridItemHTMLElement, GridStack } from 'fily-publish-gridstack';
import { GridItemHTMLElement } from 'fily-publish-gridstack';
import { MutableRefObject, RefObject, useMemo } from 'react';
import { AppItem, Item, WidgetItem } from '~/components/Board/context';
import { AppType } from '~/types/app';
import { WidgetWrapper } from '~/widgets/WidgetWrapper';
import { IWidget, IWidgetDefinition } from '~/widgets/widgets';
import Widgets from '../../../widgets';
import { appTileDefinition } from '../Tiles/Apps/AppTile';
import { GridstackTileWrapper } from '../Tiles/TileWrapper';
import { useGridstackStore } from './gridstack/store';
import { BoardAppItem } from '../Items/App/AppItem';
import { GridstackItemWrapper } from '../Items/GridstackItemWrapper';
interface WrapperContentProps {
interface SectionContentProps {
items: Item[];
refs: {
wrapper: RefObject<HTMLDivElement>;
@@ -18,36 +15,36 @@ interface WrapperContentProps {
};
}
export function WrapperContent({ items, refs }: WrapperContentProps) {
export function SectionContent({ items, refs }: SectionContentProps) {
const apps = useMemo(() => items.filter((x): x is AppItem => x.type === 'app'), [items]);
const widgets = useMemo(() => items.filter((x): x is WidgetItem => x.type === 'widget'), [items]);
return (
<>
{apps?.map((app) => {
const { component: TileComponent, ...tile } = appTileDefinition;
return (
<GridstackTileWrapper
id={app.id}
type="app"
key={app.id}
itemRef={refs.items.current[app.id]}
{...tile}
x={app.x}
y={app.y}
width={app.width}
height={app.height}
>
<TileComponent className="grid-stack-item-content" app={app} />
</GridstackTileWrapper>
);
})}
{apps?.map((app) => (
<GridstackItemWrapper
id={app.id}
type="app"
key={app.id}
itemRef={refs.items.current[app.id]}
maxHeight={12}
maxWidth={12}
minHeight={1}
minWidth={1}
x={app.x}
y={app.y}
width={app.width}
height={app.height}
>
<BoardAppItem className="grid-stack-item-content" app={app} />
</GridstackItemWrapper>
))}
{widgets.map((widget) => {
const definition = Widgets[widget.sort];
if (!definition) return null;
return (
<GridstackTileWrapper
<GridstackItemWrapper
type="widget"
key={widget.id}
itemRef={refs.items.current[widget.id]}
@@ -61,10 +58,9 @@ export function WrapperContent({ items, refs }: WrapperContentProps) {
<WidgetWrapper
className="grid-stack-item-content"
widget={widget}
widgetType={widget.sort}
WidgetComponent={definition.component as any}
/>
</GridstackTileWrapper>
</GridstackItemWrapper>
);
})}
</>

View File

@@ -2,7 +2,7 @@ import { Drawer, Title } from '@mantine/core';
import { useTranslation } from 'next-i18next';
import { SidebarSection } from '~/components/Board/context';
import { DashboardSidebar } from '../../Wrappers/Sidebar/Sidebar';
import { DashboardSidebar } from '../SidebarSection';
interface MobileRibbonSidebarDrawerProps {
onClose: () => void;
@@ -32,7 +32,7 @@ export const MobileRibbonSidebarDrawer = ({
transitionProps={{ transition: `slide-${section.position === 'right' ? 'left' : 'right'}` }}
{...props}
>
<DashboardSidebar section={section} isGridstackReady />
<DashboardSidebar section={section} />
</Drawer>
);
};

View File

@@ -0,0 +1,46 @@
import { Card } from '@mantine/core';
import { RefObject } from 'react';
import { SidebarSection } from '~/components/Board/context';
import { useCardStyles } from '../../../layout/Common/useCardStyles';
import { useGridstack } from '../../gridstack/use-gridstack';
import { SectionContent } from '../SectionContent';
interface DashboardSidebarProps extends DashboardSidebarInnerProps {
section: SidebarSection;
}
// TODO: Move mobile ribons in this directory too!
export const DashboardSidebar = ({ section }: DashboardSidebarProps) => {
const {
classes: { card: cardClass },
} = useCardStyles(true);
const { refs } = useGridstack({ section });
const minRow = useMinRowForFullHeight(refs.wrapper);
return (
<Card p={0} m={0} radius="lg" className={cardClass} withBorder>
<div
ref={refs.wrapper}
className="grid-stack grid-stack-sidebar"
style={{
transitionDuration: '0s',
minWidth: 256,
height: '100%',
width: '100%',
}}
data-sidebar={section.id}
gs-min-row={minRow}
>
<SectionContent items={section.items} refs={refs} />
</div>{' '}
</Card>
);
};
interface DashboardSidebarInnerProps {
section: SidebarSection;
}
const useMinRowForFullHeight = (wrapperRef: RefObject<HTMLDivElement>) =>
wrapperRef.current ? Math.floor(wrapperRef.current!.offsetHeight / 128) : 2;

View File

@@ -1,9 +1,9 @@
import { ContextModalProps } from '@mantine/modals';
import { useState } from 'react';
import { AvailableElementTypes } from './Components/Overview/AvailableElementsOverview';
import { AvailableStaticTypes } from './Components/StaticElementsTab/AvailableStaticElementsTab';
import { AvailableIntegrationElements } from './Components/WidgetsTab/AvailableWidgetsTab';
import { AvailableElementTypes } from './Overview/AvailableElementsOverview';
import { AvailableStaticTypes } from './StaticElementsTab/AvailableStaticElementsTab';
import { AvailableIntegrationElements } from './WidgetsTab/AvailableWidgetsTab';
export const SelectElementModal = ({ context, id }: ContextModalProps) => {
const [activeTab, setActiveTab] = useState<undefined | 'integrations' | 'static_elements'>();

View File

@@ -1,7 +1,7 @@
import { Grid, Text } from '@mantine/core';
import { useTranslation } from 'next-i18next';
import widgets from '../../../../../../widgets';
import widgets from '../../../../widgets';
import { SelectorBackArrow } from '../Shared/SelectorBackArrow';
import { WidgetElementType } from './WidgetElementType';

View File

@@ -3,11 +3,11 @@ import { showNotification } from '@mantine/notifications';
import { Icon, IconChecks } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { v4 as uuidv4 } from 'uuid';
import { useConfigContext } from '~/config/provider';
import { useConfigStore } from '~/config/store';
import { IWidget, IWidgetDefinition } from '~/widgets/widgets';
import { useEditModeStore } from '../../../../Views/useEditModeStore';
import { useEditModeStore } from '../../useEditModeStore';
import { GenericAvailableElementType } from '../Shared/GenericElementType';
interface WidgetElementTypeProps {

View File

@@ -7,10 +7,10 @@ import {
useMemo,
useRef,
} from 'react';
import { useItemActions } from '~/components/Board/Items/item-actions';
import { type Section, useRequiredBoard } from '~/components/Board/context';
import { useItemActions } from '~/components/Board/item-actions';
import { useEditModeStore } from '../../Views/useEditModeStore';
import { useEditModeStore } from '../useEditModeStore';
import { initializeGridstack } from './init-gridstack';
import { useGridstackStore, useWrapperColumnCount } from './store';

View File

@@ -1,4 +1,4 @@
import { useGridItemRef } from '../item/context';
import { useGridItemRef } from '../Items/context';
import { useGridstackRef } from './context';
type ResizeGridItemProps = {

View File

@@ -1,12 +0,0 @@
import { MobileRibbons } from './Mobile/Ribbon/MobileRibbon';
import { BoardView } from './Views/DashboardView';
export const Board = () => {
return (
<>
{/* The following elemens are splitted because gridstack doesn't reinitialize them when using same item. */}
<BoardView />
<MobileRibbons />
</>
);
};

View File

@@ -1 +0,0 @@
export type EditAppModalTab = 'general' | 'behaviour' | 'network' | 'appereance' | 'integration';

View File

@@ -1,5 +0,0 @@
interface ServiceIconProps {
size: '100%' | number;
}
export const AppIcon = ({ size }: ServiceIconProps) => null;

View File

@@ -1,6 +0,0 @@
import { HomarrCardWrapper } from './HomarrCardWrapper';
import { BaseTileProps } from './type';
export const EmptyTile = ({ className }: BaseTileProps) => (
<HomarrCardWrapper className={className}>Empty</HomarrCardWrapper>
);

View File

@@ -1,3 +0,0 @@
export interface BaseTileProps {
className?: string;
}

View File

@@ -1,57 +0,0 @@
import { Card } from '@mantine/core';
import { RefObject } from 'react';
import { SidebarSection } from '~/components/Board/context';
import { useCardStyles } from '../../../layout/Common/useCardStyles';
import { WrapperContent } from '../WrapperContent';
import { useGridstack } from '../gridstack/use-gridstack';
interface DashboardSidebarProps extends DashboardSidebarInnerProps {
section: SidebarSection;
isGridstackReady: boolean;
}
export const DashboardSidebar = ({ section, isGridstackReady }: DashboardSidebarProps) => {
const {
cx,
classes: { card: cardClass },
} = useCardStyles(true);
return (
<Card p={0} m={0} radius="lg" className={cardClass} withBorder>
{isGridstackReady && <SidebarInner section={section} />}
</Card>
);
};
interface DashboardSidebarInnerProps {
section: SidebarSection;
}
// Is Required because of the gridstack main area width.
const SidebarInner = ({ section }: DashboardSidebarInnerProps) => {
const { refs } = useGridstack({ section });
const minRow = useMinRowForFullHeight(refs.wrapper);
return (
<div
ref={refs.wrapper}
className="grid-stack grid-stack-sidebar"
style={{
transitionDuration: '0s',
minWidth: 256,
height: '100%',
width: '100%',
}}
data-sidebar={section.id}
// eslint-disable-next-line react/no-unknown-property
gs-min-row={minRow}
>
<WrapperContent items={section.items} refs={refs} />
</div>
);
};
const useMinRowForFullHeight = (wrapperRef: RefObject<HTMLDivElement>) =>
wrapperRef.current ? Math.floor(wrapperRef.current!.offsetHeight / 128) : 2;

View File

@@ -15,8 +15,8 @@ import { Trans, useTranslation } from 'next-i18next';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useRequiredBoard } from '~/components/Board/context';
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useNamedWrapperColumnCount } from '~/components/Dashboard/Wrappers/gridstack/store';
import { useNamedWrapperColumnCount } from '~/components/Board/gridstack/store';
import { useEditModeStore } from '~/components/Board/useEditModeStore';
import { BoardHeadOverride } from '~/components/layout/Meta/BoardHeadOverride';
import { HeaderActionButton } from '~/components/layout/header/ActionButton';
import { api } from '~/utils/api';

View File

@@ -20,7 +20,7 @@ import Image from 'next/image';
import { useRouter } from 'next/router';
import React, { useMemo } from 'react';
import { z } from 'zod';
import { availableIntegrations } from '~/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector';
import { availableIntegrations } from '~/components/Board/Items/App/Edit/IntegrationTab/InputElements/IntegrationSelector';
import { useConfigContext } from '~/config/provider';
import { RequestModal } from '~/modules/overseerr/RequestModal';
import { RouterOutputs, api } from '~/utils/api';

View File

@@ -1,9 +1,9 @@
import { ChangeAppPositionModal } from '~/components/Board/Items/App/ChangeAppPositionModal';
import { EditAppModal } from '~/components/Board/Items/App/EditAppModal';
import { ChangeWidgetPositionModal } from '~/components/Board/Items/Widget/ChangeWidgetPositionModal';
import { WidgetsEditModal } from '~/components/Board/Items/Widget/WidgetsEditModal';
import { CategoryEditModal } from '~/components/Board/Sections/Category/CategoryEditModal';
import { ChangeAppPositionModal } from '~/components/Dashboard/Modals/ChangePosition/ChangeAppPositionModal';
import { ChangeWidgetPositionModal } from '~/components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal';
import { EditAppModal } from '~/components/Dashboard/Modals/EditAppModal/EditAppModal';
import { SelectElementModal } from '~/components/Dashboard/Modals/SelectElement/SelectElementModal';
import { WidgetsEditModal } from '~/components/Dashboard/Tiles/Widgets/WidgetsEditModal';
import { SelectElementModal } from '~/components/Board/SelectElement/SelectElementModal';
import { CreateBoardModal } from './components/Manage/Board/create-board.modal';
import { DeleteBoardModal } from './components/Manage/Board/delete-board.modal';

View File

@@ -2,8 +2,8 @@ import { TRPCError } from '@trpc/server';
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
import { SSRConfig } from 'next-i18next';
import { z } from 'zod';
import { Board } from '~/components/Board/Board';
import { BoardProvider } from '~/components/Board/context';
import { Board } from '~/components/Dashboard/Dashboard';
import { BoardLayout } from '~/components/layout/Templates/BoardLayout';
import { env } from '~/env';
import { createTrpcServersideHelpers } from '~/server/api/helper';

View File

@@ -1,8 +1,8 @@
import { TRPCError } from '@trpc/server';
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
import { SSRConfig } from 'next-i18next';
import { Board } from '~/components/Board/Board';
import { BoardProvider } from '~/components/Board/context';
import { Board } from '~/components/Dashboard/Dashboard';
import { BoardLayout } from '~/components/layout/Templates/BoardLayout';
import { env } from '~/env';
import { createTrpcServersideHelpers } from '~/server/api/helper';

View File

@@ -1,21 +1,19 @@
import { ComponentType } from 'react';
import { ItemWrapper } from '~/components/Board/Items/ItemWrapper';
import { WidgetsMenu } from '~/components/Board/Items/Widget/WidgetsMenu';
import { WidgetItem } from '~/components/Board/context';
import { HomarrCardWrapper } from '~/components/Dashboard/Tiles/HomarrCardWrapper';
import { WidgetsMenu } from '~/components/Dashboard/Tiles/Widgets/WidgetsMenu';
import Widgets from '.';
import ErrorBoundary from './boundary';
import { IWidget } from './widgets';
interface WidgetWrapperProps {
widgetType: string;
widget: WidgetItem;
className: string;
WidgetComponent: ComponentType<{ widget: WidgetItem }>;
}
// If a property has no value, set it to the default value
const useWidget = <T extends WidgetItem>(widget: T): T => {
const useWidgetWithDefaultOptionValues = <T extends WidgetItem>(widget: T): T => {
const definition = Widgets[widget.sort];
const newProps = { ...widget.options };
@@ -32,20 +30,15 @@ const useWidget = <T extends WidgetItem>(widget: T): T => {
};
};
export const WidgetWrapper = ({
widgetType,
widget,
className,
WidgetComponent,
}: WidgetWrapperProps) => {
const widgetWithDefaultProps = useWidget(widget);
export const WidgetWrapper = ({ widget, className, WidgetComponent }: WidgetWrapperProps) => {
const widgetWithDefaultProps = useWidgetWithDefaultOptionValues(widget);
return (
<ErrorBoundary integration={widgetType} widget={widgetWithDefaultProps}>
<HomarrCardWrapper className={className}>
<WidgetsMenu type={widgetType} widget={widgetWithDefaultProps} />
<ErrorBoundary widget={widgetWithDefaultProps}>
<ItemWrapper className={className}>
<WidgetsMenu widget={widgetWithDefaultProps} />
<WidgetComponent widget={widgetWithDefaultProps} />
</HomarrCardWrapper>
</ItemWrapper>
</ErrorBoundary>
);
};

View File

@@ -30,7 +30,7 @@ import { useEffect } from 'react';
import React from 'react';
import { v4 } from 'uuid';
import { z } from 'zod';
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useEditModeStore } from '~/components/Board/useEditModeStore';
import { IconSelector } from '~/components/IconSelector/IconSelector';
import { defineWidget } from '../helper';

View File

@@ -4,10 +4,8 @@ import { IconBrandGithub, IconBug, IconInfoCircle, IconRefresh } from '@tabler/i
import Consola from 'consola';
import { withTranslation } from 'next-i18next';
import React, { ReactNode } from 'react';
import { WidgetsMenu } from '~/components/Board/Items/Widget/WidgetsMenu';
import { WidgetItem } from '~/components/Board/context';
import { WidgetsMenu } from '~/components/Dashboard/Tiles/Widgets/WidgetsMenu';
import { IWidget } from './widgets';
type ErrorBoundaryState = {
hasError: boolean;
@@ -17,7 +15,6 @@ type ErrorBoundaryState = {
type ErrorBoundaryProps = {
t: (key: string) => string;
children: ReactNode;
integration: string;
widget: WidgetItem;
};
@@ -56,7 +53,7 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta
withBorder
h="calc(100% - 20px)"
>
<WidgetsMenu type={this.props.integration} widget={this.props.widget} />
<WidgetsMenu widget={this.props.widget} />
<ScrollArea h="100%" type="auto" offsetScrollbars>
<Center>
<Stack align="center" spacing="xs">

View File

@@ -3,7 +3,7 @@ import { Calendar } from '@mantine/dates';
import { IconCalendarTime } from '@tabler/icons-react';
import { useSession } from 'next-auth/react';
import { useState } from 'react';
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useEditModeStore } from '~/components/Board/useEditModeStore';
import { useConfigContext } from '~/config/provider';
import { getLanguageByCode } from '~/tools/language';
import { RouterOutputs, api } from '~/utils/api';

View File

@@ -6,7 +6,7 @@ import { BubbleMenu, useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import { useState } from 'react';
import { useRequiredBoard } from '~/components/Board/context';
import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore';
import { useEditModeStore } from '~/components/Board/useEditModeStore';
import { useColorTheme } from '~/tools/color';
import { api } from '~/utils/api';