mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 15:35:55 +01:00
🎨 Improved changeability of wrappers with new wrapper content component
This commit is contained in:
@@ -8,13 +8,14 @@ import { GridstackTileWrapper } from '../../Tiles/TileWrapper';
|
|||||||
import { useEditModeStore } from '../../Views/useEditModeStore';
|
import { useEditModeStore } from '../../Views/useEditModeStore';
|
||||||
import { useGridstack } from '../gridstack/use-gridstack';
|
import { useGridstack } from '../gridstack/use-gridstack';
|
||||||
import { CategoryEditMenu } from './CategoryEditMenu';
|
import { CategoryEditMenu } from './CategoryEditMenu';
|
||||||
|
import { WrapperContent } from '../WrapperContent';
|
||||||
|
|
||||||
interface DashboardCategoryProps {
|
interface DashboardCategoryProps {
|
||||||
category: CategoryType;
|
category: CategoryType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
|
export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
|
||||||
const { refs, items, widgets } = useGridstack('category', category.id);
|
const { refs, apps, widgets } = useGridstack('category', category.id);
|
||||||
const isEditMode = useEditModeStore((x) => x.enabled);
|
const isEditMode = useEditModeStore((x) => x.enabled);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -29,42 +30,7 @@ export const DashboardCategory = ({ category }: DashboardCategoryProps) => {
|
|||||||
data-category={category.id}
|
data-category={category.id}
|
||||||
ref={refs.wrapper}
|
ref={refs.wrapper}
|
||||||
>
|
>
|
||||||
{items?.map((app) => {
|
<WrapperContent apps={apps} refs={refs} widgets={widgets} />
|
||||||
const { component: TileComponent, ...tile } = Tiles['app'];
|
|
||||||
return (
|
|
||||||
<GridstackTileWrapper
|
|
||||||
id={app.id}
|
|
||||||
type="app"
|
|
||||||
key={app.id}
|
|
||||||
itemRef={refs.items.current[app.id]}
|
|
||||||
{...tile}
|
|
||||||
{...app.shape.location}
|
|
||||||
{...app.shape.size}
|
|
||||||
>
|
|
||||||
<TileComponent className="grid-stack-item-content" app={app} />
|
|
||||||
</GridstackTileWrapper>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{widgets.map((widget) => {
|
|
||||||
const definition = Widgets[widget.id as keyof typeof Widgets] as
|
|
||||||
| IWidgetDefinition
|
|
||||||
| undefined;
|
|
||||||
if (!definition) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<GridstackTileWrapper
|
|
||||||
type="widget"
|
|
||||||
key={widget.id}
|
|
||||||
itemRef={refs.items.current[widget.id]}
|
|
||||||
id={definition.id}
|
|
||||||
{...definition.gridstack}
|
|
||||||
{...widget.shape.location}
|
|
||||||
{...widget.shape.size}
|
|
||||||
>
|
|
||||||
<definition.component className="grid-stack-item-content" widget={widget} />
|
|
||||||
</GridstackTileWrapper>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</HomarrCardWrapper>
|
</HomarrCardWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import { Tiles } from '../../Tiles/tilesDefinitions';
|
|||||||
import Widgets from '../../../../widgets';
|
import Widgets from '../../../../widgets';
|
||||||
import { GridstackTileWrapper } from '../../Tiles/TileWrapper';
|
import { GridstackTileWrapper } from '../../Tiles/TileWrapper';
|
||||||
import { useGridstack } from '../gridstack/use-gridstack';
|
import { useGridstack } from '../gridstack/use-gridstack';
|
||||||
|
import { WrapperContent } from '../WrapperContent';
|
||||||
|
|
||||||
interface DashboardSidebarProps {
|
interface DashboardSidebarProps {
|
||||||
location: 'right' | 'left';
|
location: 'right' | 'left';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DashboardSidebar = ({ location }: DashboardSidebarProps) => {
|
export const DashboardSidebar = ({ location }: DashboardSidebarProps) => {
|
||||||
const { refs, items, widgets } = useGridstack('sidebar', location);
|
const { refs, apps, widgets } = useGridstack('sidebar', location);
|
||||||
|
|
||||||
const minRow = useMinRowForFullHeight(refs.wrapper);
|
const minRow = useMinRowForFullHeight(refs.wrapper);
|
||||||
|
|
||||||
@@ -31,42 +32,7 @@ export const DashboardSidebar = ({ location }: DashboardSidebarProps) => {
|
|||||||
gs-min-row={minRow}
|
gs-min-row={minRow}
|
||||||
ref={refs.wrapper}
|
ref={refs.wrapper}
|
||||||
>
|
>
|
||||||
{items.map((app) => {
|
<WrapperContent apps={apps} refs={refs} widgets={widgets} />
|
||||||
const { component: TileComponent, ...tile } = Tiles['app'];
|
|
||||||
return (
|
|
||||||
<GridstackTileWrapper
|
|
||||||
id={app.id}
|
|
||||||
type="app"
|
|
||||||
key={app.id}
|
|
||||||
itemRef={refs.items.current[app.id]}
|
|
||||||
{...tile}
|
|
||||||
{...app.shape.location}
|
|
||||||
{...app.shape.size}
|
|
||||||
>
|
|
||||||
<TileComponent className="grid-stack-item-content" app={app} />
|
|
||||||
</GridstackTileWrapper>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{widgets.map((widget) => {
|
|
||||||
const definition = Widgets[widget.id as keyof typeof Widgets] as
|
|
||||||
| IWidgetDefinition
|
|
||||||
| undefined;
|
|
||||||
if (!definition) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<GridstackTileWrapper
|
|
||||||
type="widget"
|
|
||||||
key={widget.id}
|
|
||||||
itemRef={refs.items.current[widget.id]}
|
|
||||||
id={definition.id}
|
|
||||||
{...definition.gridstack}
|
|
||||||
{...widget.shape.location}
|
|
||||||
{...widget.shape.size}
|
|
||||||
>
|
|
||||||
<definition.component className="grid-stack-item-content" widget={widget} />
|
|
||||||
</GridstackTileWrapper>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import { WrapperType } from '../../../../types/wrapper';
|
import { WrapperType } from '../../../../types/wrapper';
|
||||||
import Widgets from '../../../../widgets';
|
|
||||||
import { IWidget, IWidgetDefinition } from '../../../../widgets/widgets';
|
|
||||||
import { Tiles } from '../../Tiles/tilesDefinitions';
|
|
||||||
import { GridstackTileWrapper } from '../../Tiles/TileWrapper';
|
|
||||||
import { useGridstack } from '../gridstack/use-gridstack';
|
import { useGridstack } from '../gridstack/use-gridstack';
|
||||||
|
import { WrapperContent } from '../WrapperContent';
|
||||||
|
|
||||||
interface DashboardWrapperProps {
|
interface DashboardWrapperProps {
|
||||||
wrapper: WrapperType;
|
wrapper: WrapperType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DashboardWrapper = ({ wrapper }: DashboardWrapperProps) => {
|
export const DashboardWrapper = ({ wrapper }: DashboardWrapperProps) => {
|
||||||
const { refs, items, widgets } = useGridstack('wrapper', wrapper.id);
|
const { refs, apps, widgets } = useGridstack('wrapper', wrapper.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -19,42 +16,7 @@ export const DashboardWrapper = ({ wrapper }: DashboardWrapperProps) => {
|
|||||||
data-wrapper={wrapper.id}
|
data-wrapper={wrapper.id}
|
||||||
ref={refs.wrapper}
|
ref={refs.wrapper}
|
||||||
>
|
>
|
||||||
{items?.map((app) => {
|
<WrapperContent apps={apps} refs={refs} widgets={widgets} />
|
||||||
const { component: TileComponent, ...tile } = Tiles['app'];
|
|
||||||
return (
|
|
||||||
<GridstackTileWrapper
|
|
||||||
id={app.id}
|
|
||||||
type="app"
|
|
||||||
key={app.id}
|
|
||||||
itemRef={refs.items.current[app.id]}
|
|
||||||
{...tile}
|
|
||||||
{...app.shape.location}
|
|
||||||
{...app.shape.size}
|
|
||||||
>
|
|
||||||
<TileComponent className="grid-stack-item-content" app={app} />
|
|
||||||
</GridstackTileWrapper>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{widgets.map((widget) => {
|
|
||||||
const definition = Widgets[widget.id as keyof typeof Widgets] as
|
|
||||||
| IWidgetDefinition
|
|
||||||
| undefined;
|
|
||||||
if (!definition) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<GridstackTileWrapper
|
|
||||||
type="widget"
|
|
||||||
key={widget.id}
|
|
||||||
itemRef={refs.items.current[widget.id]}
|
|
||||||
id={definition.id}
|
|
||||||
{...definition.gridstack}
|
|
||||||
{...widget.shape.location}
|
|
||||||
{...widget.shape.size}
|
|
||||||
>
|
|
||||||
<definition.component className="grid-stack-item-content" widget={widget} />
|
|
||||||
</GridstackTileWrapper>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
60
src/components/Dashboard/Wrappers/WrapperContent.tsx
Normal file
60
src/components/Dashboard/Wrappers/WrapperContent.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { GridStack } from 'fily-publish-gridstack';
|
||||||
|
import { MutableRefObject, RefObject } from 'react';
|
||||||
|
import { AppType } from '../../../types/app';
|
||||||
|
import Widgets from '../../../widgets';
|
||||||
|
import { IWidget, IWidgetDefinition } from '../../../widgets/widgets';
|
||||||
|
import { Tiles } from '../Tiles/tilesDefinitions';
|
||||||
|
import { GridstackTileWrapper } from '../Tiles/TileWrapper';
|
||||||
|
|
||||||
|
interface WrapperContentProps {
|
||||||
|
apps: AppType[];
|
||||||
|
widgets: IWidget<string, any>[];
|
||||||
|
refs: {
|
||||||
|
wrapper: RefObject<HTMLDivElement>;
|
||||||
|
items: MutableRefObject<Record<string, RefObject<HTMLDivElement>>>;
|
||||||
|
gridstack: MutableRefObject<GridStack | undefined>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WrapperContent = ({ apps, refs, widgets }: WrapperContentProps) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{apps?.map((app) => {
|
||||||
|
const { component: TileComponent, ...tile } = Tiles['app'];
|
||||||
|
return (
|
||||||
|
<GridstackTileWrapper
|
||||||
|
id={app.id}
|
||||||
|
type="app"
|
||||||
|
key={app.id}
|
||||||
|
itemRef={refs.items.current[app.id]}
|
||||||
|
{...tile}
|
||||||
|
{...app.shape.location}
|
||||||
|
{...app.shape.size}
|
||||||
|
>
|
||||||
|
<TileComponent className="grid-stack-item-content" app={app} />
|
||||||
|
</GridstackTileWrapper>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{widgets.map((widget) => {
|
||||||
|
const definition = Widgets[widget.id as keyof typeof Widgets] as
|
||||||
|
| IWidgetDefinition
|
||||||
|
| undefined;
|
||||||
|
if (!definition) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GridstackTileWrapper
|
||||||
|
type="widget"
|
||||||
|
key={widget.id}
|
||||||
|
itemRef={refs.items.current[widget.id]}
|
||||||
|
id={definition.id}
|
||||||
|
{...definition.gridstack}
|
||||||
|
{...widget.shape.location}
|
||||||
|
{...widget.shape.size}
|
||||||
|
>
|
||||||
|
<definition.component className="grid-stack-item-content" widget={widget} />
|
||||||
|
</GridstackTileWrapper>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -17,7 +17,7 @@ import { useEditModeStore } from '../../Views/useEditModeStore';
|
|||||||
import { initializeGridstack } from './init-gridstack';
|
import { initializeGridstack } from './init-gridstack';
|
||||||
|
|
||||||
interface UseGristackReturnType {
|
interface UseGristackReturnType {
|
||||||
items: AppType[];
|
apps: AppType[];
|
||||||
widgets: IWidget<string, any>[];
|
widgets: IWidget<string, any>[];
|
||||||
refs: {
|
refs: {
|
||||||
wrapper: RefObject<HTMLDivElement>;
|
wrapper: RefObject<HTMLDivElement>;
|
||||||
@@ -211,7 +211,7 @@ export const useGridstack = (
|
|||||||
}, [items.length, wrapperRef.current, (widgets ?? []).length]);
|
}, [items.length, wrapperRef.current, (widgets ?? []).length]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
apps: items,
|
||||||
widgets: widgets ?? [],
|
widgets: widgets ?? [],
|
||||||
refs: {
|
refs: {
|
||||||
items: itemRefs,
|
items: itemRefs,
|
||||||
|
|||||||
20
src/widgets/WidgetWrapper.tsx
Normal file
20
src/widgets/WidgetWrapper.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
import { HomarrCardWrapper } from '../components/Dashboard/Tiles/HomarrCardWrapper';
|
||||||
|
import { WidgetsMenu } from '../components/Dashboard/Tiles/Widgets/WidgetsMenu';
|
||||||
|
import { IWidget } from './widgets';
|
||||||
|
|
||||||
|
interface WidgetWrapperProps {
|
||||||
|
widgetId: string;
|
||||||
|
widget: IWidget<string, any>;
|
||||||
|
className: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WidgetWrapper = ({ widgetId, widget, className, children }: WidgetWrapperProps) => {
|
||||||
|
return (
|
||||||
|
<HomarrCardWrapper className={className}>
|
||||||
|
<WidgetsMenu integration={widgetId} widget={widget} />
|
||||||
|
{children}
|
||||||
|
</HomarrCardWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user