From 8d4b8b788163e684dd5ad638f30071cb73d0bd25 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Thu, 31 Oct 2024 17:21:25 +0000 Subject: [PATCH] Refactor DashboardToolbar component to adjust margins and spacing --- Common/Types/Dashboard/DashboardSize.ts | 94 +++++++++++- .../Components/DashboardTextComponent.ts | 4 +- .../Dashboard/Canvas/BlankCanvas.tsx | 6 +- .../Components/Dashboard/Canvas/BlankRow.tsx | 4 + .../Dashboard/Canvas/DashboardUnit.tsx | 18 ++- .../src/Components/Dashboard/Canvas/Index.tsx | 6 + .../Components/DashboardBaseComponent.tsx | 142 +++++++++++------- .../Components/Dashboard/DashboardView.tsx | 33 +++- .../Dashboard/Toolbar/DashboardToolbar.tsx | 2 +- 9 files changed, 238 insertions(+), 71 deletions(-) diff --git a/Common/Types/Dashboard/DashboardSize.ts b/Common/Types/Dashboard/DashboardSize.ts index cc0d028378..2f1f727351 100644 --- a/Common/Types/Dashboard/DashboardSize.ts +++ b/Common/Types/Dashboard/DashboardSize.ts @@ -7,17 +7,97 @@ const DefaultDashboardSize: DashboardSize = { widthInDashboardUnits: 12, heightInDashboardUnits: 60, }; -// 5 rem is the dashboard unit width, and 0.94 is margin between those units. -export const DashboardRemConversionFactor: number = 5.94; +export const SpaceBetweenUnitsInPx: number = 10; +export const MarginForEachUnitInPx: number = 10 / 2; -export const DahboardHeightUnitInRem: number = 5; +type GetDashboardUnitWidthInPxFunction = ( + currentTotalDashboardWidthInPx: number, +) => number; -export const DashboardWidthUnitInRem: number = 5; +export const GetDashboardUnitWidthInPx: GetDashboardUnitWidthInPxFunction = ( + currentTotalDashboardWidthInPx: number, +): number => { + return ( + (currentTotalDashboardWidthInPx - + (DefaultDashboardSize.widthInDashboardUnits - 1) * + SpaceBetweenUnitsInPx) / + DefaultDashboardSize.widthInDashboardUnits + ); +}; + + +type GetDashboardUnitHeightInPxFunction = ( + currentTotalDashboardWidthInPx: number, +) => number; + +export const GetDashboardUnitHeightInPx: GetDashboardUnitHeightInPxFunction = ( + currentTotalDashboardWidthInPx: number, +): number => { + return GetDashboardUnitWidthInPx(currentTotalDashboardWidthInPx); // its a square, so height is the same as width +}; + +type GetHeightOfDashboardComponentFunction = ( + heightInDashboardUnits: number, + totalCurrentDashboardWidthInPx: number, +) => number; + +export const GetHeightOfDashboardComponent: GetHeightOfDashboardComponentFunction = ( + heightInDashboardUnits: number, + totalCurrentDashboardWidthInPx: number, +): number => { + return ( + heightInDashboardUnits * + GetDashboardUnitHeightInPx(totalCurrentDashboardWidthInPx) + + (heightInDashboardUnits - 1) * SpaceBetweenUnitsInPx + ); +}; -export const DashboardSpaceBetweenUnitsInRem: number = 0.94; +type GetWidthOfDashboardComponentFunction = ( + widthInDashboardUnits: number, + totalCurrentDashboardWidthInPx: number, +) => number; -export const TotalWidthOfDashboardInRem: number = - DefaultDashboardSize.widthInDashboardUnits * DashboardRemConversionFactor; +export const GetWidthOfDashboardComponent: GetWidthOfDashboardComponentFunction = ( + widthInDashboardUnits: number, + totalCurrentDashboardWidthInPx: number, +): number => { + return ( + widthInDashboardUnits * + GetDashboardUnitWidthInPx(totalCurrentDashboardWidthInPx) + + (widthInDashboardUnits - 1) * SpaceBetweenUnitsInPx + ); +}; + +type GetDashboardComponentWidthInDashboardUnitsFunction = ( + currentTotalDashboardWidthInPx: number, + componentWidthInPx: number, +) => number; + +export const GetDashboardComponentWidthInDashboardUnits: GetDashboardComponentWidthInDashboardUnitsFunction = ( + currentTotalDashboardWidthInPx: number, + componentWidthInPx: number, +): number => { + return Math.floor( + (componentWidthInPx + (DefaultDashboardSize.widthInDashboardUnits - 1) * SpaceBetweenUnitsInPx) / + GetDashboardUnitWidthInPx(currentTotalDashboardWidthInPx), + ); +} + + +type GetDashboardComponentHeightInDashboardUnitsFunction = ( + currentTotalDashboardWidthInPx: number, + componentHeightInPx: number, +) => number; + +export const GetDashboardComponentHeightInDashboardUnits: GetDashboardComponentHeightInDashboardUnitsFunction = ( + currentTotalDashboardWidthInPx: number, + componentHeightInPx: number, +): number => { + return Math.floor( + (componentHeightInPx + (DefaultDashboardSize.heightInDashboardUnits - 1) * SpaceBetweenUnitsInPx) / + GetDashboardUnitHeightInPx(currentTotalDashboardWidthInPx), + ); +} export default DefaultDashboardSize; diff --git a/Common/Utils/Dashboard/Components/DashboardTextComponent.ts b/Common/Utils/Dashboard/Components/DashboardTextComponent.ts index f5485b9c91..191d46a026 100644 --- a/Common/Utils/Dashboard/Components/DashboardTextComponent.ts +++ b/Common/Utils/Dashboard/Components/DashboardTextComponent.ts @@ -7,8 +7,8 @@ export default class DashboardTextComponentUtil extends DashboardBaseComponentUt public static override getDefaultComponent(): DashboardTextComponent { return { _type: ObjectType.DashboardTextComponent, - widthInDashboardUnits: 12, - heightInDashboardUnits: 1, + widthInDashboardUnits: 6, + heightInDashboardUnits: 3, topInDashboardUnits: 0, leftInDashboardUnits: 0, text: "Hello, World!", diff --git a/Dashboard/src/Components/Dashboard/Canvas/BlankCanvas.tsx b/Dashboard/src/Components/Dashboard/Canvas/BlankCanvas.tsx index 345ef8a1c6..8a7d31a3eb 100644 --- a/Dashboard/src/Components/Dashboard/Canvas/BlankCanvas.tsx +++ b/Dashboard/src/Components/Dashboard/Canvas/BlankCanvas.tsx @@ -7,6 +7,7 @@ export interface ComponentProps { dashboardViewConfig: DashboardViewConfig; onClick: (top: number, left: number) => void; isEditMode: boolean; + totalCurrentDashboardWidthInPx: number; } const BlankCanvasElement: FunctionComponent = ( @@ -20,7 +21,7 @@ const BlankCanvasElement: FunctionComponent = ( if (!props.isEditMode && props.dashboardViewConfig.components.length === 0) { return ( -
+
No components added to this dashboard. Please add one to get started.
); @@ -33,6 +34,9 @@ const BlankCanvasElement: FunctionComponent = ( return ( { diff --git a/Dashboard/src/Components/Dashboard/Canvas/BlankRow.tsx b/Dashboard/src/Components/Dashboard/Canvas/BlankRow.tsx index 9c0f159f26..c25734625e 100644 --- a/Dashboard/src/Components/Dashboard/Canvas/BlankRow.tsx +++ b/Dashboard/src/Components/Dashboard/Canvas/BlankRow.tsx @@ -6,6 +6,7 @@ export interface ComponentProps { rowNumber: number; onClick: (top: number, left: number) => void; isEditMode: boolean; + totalCurrentDashboardWidthInPx: number; } const BlankRowElement: FunctionComponent = ( @@ -19,6 +20,9 @@ const BlankRowElement: FunctionComponent = ( (_: number, index: number) => { return ( { diff --git a/Dashboard/src/Components/Dashboard/Canvas/DashboardUnit.tsx b/Dashboard/src/Components/Dashboard/Canvas/DashboardUnit.tsx index 82048bb607..af6933de88 100644 --- a/Dashboard/src/Components/Dashboard/Canvas/DashboardUnit.tsx +++ b/Dashboard/src/Components/Dashboard/Canvas/DashboardUnit.tsx @@ -1,14 +1,25 @@ +import { + GetDashboardUnitHeightInPx, + MarginForEachUnitInPx, +} from "Common/Types/Dashboard/DashboardSize"; import React, { FunctionComponent, ReactElement } from "react"; export interface ComponentProps { isEditMode: boolean; onClick: () => void; + currentTotalDashboardWidthInPx: number; } const DashboardUnitElement: FunctionComponent = ( props: ComponentProps, ): ReactElement => { - let className: string = "m-2 h-20 w-20 min-w-20 min-h-20 "; + const heightOfUnitInPx: number = GetDashboardUnitHeightInPx( + props.currentTotalDashboardWidthInPx, + ); + + const widthOfUnitInPx: number = heightOfUnitInPx; // its a square + + let className: string = ""; if (props.isEditMode) { className += @@ -21,6 +32,11 @@ const DashboardUnitElement: FunctionComponent = ( onClick={() => { props.onClick(); }} + style={{ + width: widthOfUnitInPx + "px", + height: heightOfUnitInPx + "px", + margin: MarginForEachUnitInPx + "px", + }} >
); }; diff --git a/Dashboard/src/Components/Dashboard/Canvas/Index.tsx b/Dashboard/src/Components/Dashboard/Canvas/Index.tsx index 501ea94687..2cac46103a 100644 --- a/Dashboard/src/Components/Dashboard/Canvas/Index.tsx +++ b/Dashboard/src/Components/Dashboard/Canvas/Index.tsx @@ -11,6 +11,7 @@ export interface ComponentProps { dashboardViewConfig: DashboardViewConfig; onDashboardViewConfigChange: (newConfig: DashboardViewConfig) => void; isEditMode: boolean; + currentTotalDashboardWidthInPx: number; } const DashboardCanvas: FunctionComponent = ( @@ -83,6 +84,9 @@ const DashboardCanvas: FunctionComponent = ( // render a blank unit renderedComponents.push( { @@ -125,6 +129,7 @@ const DashboardCanvas: FunctionComponent = ( return ( = ( ) { return ( {}} dashboardViewConfig={props.dashboardViewConfig} diff --git a/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx b/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx index 51dd1d3ec7..c2248380d8 100644 --- a/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx +++ b/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx @@ -7,11 +7,7 @@ import { ObjectType } from "Common/Types/JSON"; import DashboardChartComponent from "./DashboardChartComponent"; import DashboardValueComponent from "./DashboardValueComponent"; import DashboardTextComponent from "./DashboardTextComponent"; -import { - DahboardHeightUnitInRem, - DashboardSpaceBetweenUnitsInRem, - DashboardWidthUnitInRem, -} from "Common/Types/Dashboard/DashboardSize"; +import { GetDashboardComponentHeightInDashboardUnits, GetDashboardComponentWidthInDashboardUnits, GetDashboardUnitHeightInPx, GetDashboardUnitWidthInPx, MarginForEachUnitInPx } from "Common/Types/Dashboard/DashboardSize"; import { GetReactElementFunction } from "Common/UI/Types/FunctionTypes"; export interface DashboardCommonComponentProps @@ -25,6 +21,7 @@ export interface DashboardBaseComponentProps { isSelected: boolean; key: string; onComponentUpdate: (component: DashboardBaseComponent) => void; + totalCurrentDashboardWidthInPx: number; } export interface ComponentProps extends DashboardBaseComponentProps { @@ -37,61 +34,99 @@ const DashboardBaseComponentElement: FunctionComponent = ( const widthOfComponent: number = props.component.widthInDashboardUnits; const heightOfComponent: number = props.component.heightInDashboardUnits; - let className: string = `relative rounded m-2 col-span-${widthOfComponent} row-span-${heightOfComponent} p-2`; + let className: string = `relative rounded-md col-span-${widthOfComponent} row-span-${heightOfComponent} p-2 bg-white border-2 border-solid border-gray-100`; if (props.isEditMode) { - className += " cursor-pointer border border-solid border-gray-300 "; + className += " cursor-pointer"; } if (props.isSelected && props.isEditMode) { className += " border-2 border-blue-300"; } - const dashbordComponentRef = React.useRef(null); + const dashboardComponentRef: React.RefObject = React.useRef(null); + type MoveComponentTypeFunction = ( + moveLeftOffset: number, + moveTopOffset: number, + ) => (mouseEvent: MouseEvent) => void; - type MoveComponentTypeFunction = (moveLeftOffset: number, moveTopOffset: number) => (mouseEvent: MouseEvent) => void; - - const moveComponent: MoveComponentTypeFunction = (moveLeftOffset: number, moveTopOffset: number): (mouseEvent: MouseEvent) => void => { - + const moveComponent: MoveComponentTypeFunction = ( + moveLeftOffset: number, + moveTopOffset: number, + ): ((mouseEvent: MouseEvent) => void) => { return (event: MouseEvent) => { - - if (dashbordComponentRef.current === null) { + if (dashboardComponentRef.current === null) { return; } - dashbordComponentRef.current.style.left = event.clientX - moveLeftOffset + 'px'; - dashbordComponentRef.current.style.top = event.clientY - moveTopOffset + 'px'; - } - - } + dashboardComponentRef.current.style.left = + event.clientX - moveLeftOffset + "px"; + dashboardComponentRef.current.style.top = + event.clientY - moveTopOffset + "px"; + }; + }; let moveFunction: Function | undefined = undefined; - const resizeWidth: (event: MouseEvent) => void = (event: MouseEvent) => { - if (dashbordComponentRef.current === null) { + if (dashboardComponentRef.current === null) { return; } - dashbordComponentRef.current.style.width = event.pageX - dashbordComponentRef.current.getBoundingClientRect().left + 'px' - } + let newDashboardWidthInPx: number= + event.pageX - + dashboardComponentRef.current.getBoundingClientRect().left; + + + if(GetDashboardUnitWidthInPx(props.totalCurrentDashboardWidthInPx) > newDashboardWidthInPx) { + newDashboardWidthInPx = GetDashboardUnitWidthInPx(props.totalCurrentDashboardWidthInPx); + } + + // get this in dashboard units., + const widthInDashboardUnits: number = GetDashboardComponentWidthInDashboardUnits(props.totalCurrentDashboardWidthInPx, newDashboardWidthInPx); + + // update the component + const newComponentProps: DashboardBaseComponent = { + ...props.component, + widthInDashboardUnits: widthInDashboardUnits, + }; + + props.onComponentUpdate(newComponentProps); + }; const resizeHeight: (event: MouseEvent) => void = (event: MouseEvent) => { - if (dashbordComponentRef.current === null) { + if (dashboardComponentRef.current === null) { return; } - dashbordComponentRef.current.style.height = event.pageY - dashbordComponentRef.current.getBoundingClientRect().top + 'px' - } + + let newDashboardHeightInPx: number = event.pageY - dashboardComponentRef.current.getBoundingClientRect().top; + + if(GetDashboardUnitHeightInPx(props.totalCurrentDashboardWidthInPx) > newDashboardHeightInPx) { + newDashboardHeightInPx = GetDashboardUnitHeightInPx(props.totalCurrentDashboardWidthInPx) + } + + // get this in dashboard units + const heightInDashboardUnits: number = GetDashboardComponentHeightInDashboardUnits(props.totalCurrentDashboardWidthInPx, newDashboardHeightInPx); + + // update the component + const newComponentProps: DashboardBaseComponent = { + ...props.component, + heightInDashboardUnits: heightInDashboardUnits, + }; + + props.onComponentUpdate(newComponentProps); + }; const stopResizeAndMove: () => void = () => { - window.removeEventListener('mousemove', resizeHeight); - window.removeEventListener('mousemove', resizeWidth); + window.removeEventListener("mousemove", resizeHeight); + window.removeEventListener("mousemove", resizeWidth); if (moveFunction) { - window.removeEventListener('mousemove', moveFunction as any); + window.removeEventListener("mousemove", moveFunction as any); + moveFunction = undefined; } - window.removeEventListener('mouseup', stopResizeAndMove); - } + window.removeEventListener("mouseup", stopResizeAndMove); + }; const getResizeWidthElement: GetReactElementFunction = (): ReactElement => { if (!props.isSelected || !props.isEditMode) { @@ -106,15 +141,14 @@ const DashboardBaseComponentElement: FunctionComponent = ( }} onMouseDown={(event: React.MouseEvent) => { event.preventDefault(); - window.addEventListener('mousemove', resizeWidth); - window.addEventListener('mouseup', stopResizeAndMove); + window.addEventListener("mousemove", resizeWidth); + window.addEventListener("mouseup", stopResizeAndMove); }} className="resize-width-element cursor-ew-resize absolute right-0 w-2 h-12 bg-blue-300 hover:bg-blue-400 rounded-full cursor-pointer" > ); }; - const getMoveElement: GetReactElementFunction = (): ReactElement => { // if not selected, then return null @@ -131,15 +165,24 @@ const DashboardBaseComponentElement: FunctionComponent = ( onMouseDown={(event: React.MouseEvent) => { event.preventDefault(); - const leftOffset: number = (dashbordComponentRef.current ? dashbordComponentRef.current?.getBoundingClientRect()?.left : 0); - const topOffset: number = (dashbordComponentRef.current ? dashbordComponentRef.current.getBoundingClientRect().top : 0); + const leftOffset: number = dashboardComponentRef.current + ? dashboardComponentRef.current?.getBoundingClientRect()?.left + : 0; + const topOffset: number = dashboardComponentRef.current + ? dashboardComponentRef.current.getBoundingClientRect().top + : 0; - window.addEventListener('mousemove', moveComponent(leftOffset, topOffset)); - window.addEventListener('mouseup', stopResizeAndMove); + moveFunction = moveComponent(leftOffset, topOffset); + + window.addEventListener( + "mousemove", + moveFunction as any, + ); + window.addEventListener("mouseup", stopResizeAndMove); }} className="move-element cursor-move absolute w-4 h-4 bg-blue-300 hover:bg-blue-400 rounded-full cursor-pointer" - onDragStart={(_event: React.DragEvent) => { }} - onDragEnd={(_event: React.DragEvent) => { }} + onDragStart={(_event: React.DragEvent) => {}} + onDragEnd={(_event: React.DragEvent) => {}} > ); }; @@ -157,8 +200,8 @@ const DashboardBaseComponentElement: FunctionComponent = ( }} onMouseDown={(event: React.MouseEvent) => { event.preventDefault(); - window.addEventListener('mousemove', resizeHeight); - window.addEventListener('mouseup', stopResizeAndMove); + window.addEventListener("mousemove", resizeHeight); + window.addEventListener("mouseup", stopResizeAndMove); }} className="resize-height-element cursor-ns-resize absolute bottom-0 left-0 w-12 h-2 bg-blue-300 hover:bg-blue-400 rounded-full cursor-pointer" > @@ -191,16 +234,6 @@ const DashboardBaseComponentElement: FunctionComponent = ( ); }; - const height: number = props.component.heightInDashboardUnits; - const heightInRem: number = - height * DahboardHeightUnitInRem + - (height - 1) * DashboardSpaceBetweenUnitsInRem; - - const width: number = props.component.widthInDashboardUnits; - const widthInRem: number = - width * DashboardWidthUnitInRem + - (width - 1) * DashboardSpaceBetweenUnitsInRem; - return (
= ( props.onClick(); }} style={{ - height: `${heightInRem}rem`, - width: `${widthInRem}rem`, + margin: `${MarginForEachUnitInPx}px`, }} - ref={dashbordComponentRef} + ref={dashboardComponentRef} > {getMoveElement()} diff --git a/Dashboard/src/Components/Dashboard/DashboardView.tsx b/Dashboard/src/Components/Dashboard/DashboardView.tsx index 11a8b961a6..d12ba6f40e 100644 --- a/Dashboard/src/Components/Dashboard/DashboardView.tsx +++ b/Dashboard/src/Components/Dashboard/DashboardView.tsx @@ -2,6 +2,7 @@ import React, { FunctionComponent, ReactElement, useEffect, + useRef, useState, } from "react"; import DashboardToolbar from "./Toolbar/DashboardToolbar"; @@ -22,9 +23,7 @@ import API from "Common/UI/Utils/API/API"; import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage"; import PageLoader from "Common/UI/Components/Loader/PageLoader"; import DashboardViewConfigUtil from "Common/Utils/Dashboard/DashboardViewConfig"; -import DefaultDashboardSize, { - TotalWidthOfDashboardInRem, -} from "Common/Types/Dashboard/DashboardSize"; +import DefaultDashboardSize from "Common/Types/Dashboard/DashboardSize"; import { PromiseVoidFunction } from "Common/Types/FunctionTypes"; export interface ComponentProps { @@ -38,6 +37,29 @@ const DashboardViewer: FunctionComponent = ( DashboardMode.View, ); + // ref for dashboard div. + + const dashboardViewRef: React.RefObject = + useRef(null); + + const [dashboardTotalWidth, setDashboardTotalWidth] = useState( + dashboardViewRef.current?.offsetWidth || 0, + ); + + useEffect(() => { + setDashboardTotalWidth(dashboardViewRef.current?.offsetWidth || 0); + + const handleResize = (): void => { + setDashboardTotalWidth(dashboardViewRef.current?.offsetWidth || 0); + }; + + window.addEventListener("resize", handleResize); + + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + const [dashboardViewConfig, setDashboardViewConfig] = useState({ _type: ObjectType.DashboardViewConfig, @@ -93,8 +115,10 @@ const DashboardViewer: FunctionComponent = ( return (
= ( setDashboardViewConfig(newConfig); }} isEditMode={dashboardMode === DashboardMode.Edit} + currentTotalDashboardWidthInPx={dashboardTotalWidth} />
); diff --git a/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx b/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx index 396cc0ef04..61f008f67a 100644 --- a/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx +++ b/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx @@ -24,7 +24,7 @@ const DashboardToolbar: FunctionComponent = ( return (