From 8ddbe368cc80badd4f9ba3b9e959429978b60952 Mon Sep 17 00:00:00 2001 From: FLorial Jean Baptiste Date: Wed, 7 May 2025 11:44:01 +0200 Subject: [PATCH 1/2] [SampleCircleView] Add possibility to display single cell pucks as Circle --- .../SampleGrid/SampleCircleView.jsx | 117 ++++++++++++++++++ .../containers/SampleGridTableContainer.jsx | 19 ++- 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 ui/src/components/SampleGrid/SampleCircleView.jsx diff --git a/ui/src/components/SampleGrid/SampleCircleView.jsx b/ui/src/components/SampleGrid/SampleCircleView.jsx new file mode 100644 index 000000000..1df74b531 --- /dev/null +++ b/ui/src/components/SampleGrid/SampleCircleView.jsx @@ -0,0 +1,117 @@ +import { useEffect } from 'react'; +import { Col } from 'react-bootstrap'; +import { useDispatch, useSelector } from 'react-redux'; + +import { filterAction } from '../../actions/sampleGrid'; + +export default function SampleCircleView(props) { + const { displayPuckCellContextMenu, puckMenuID, type = 'Mockup' } = props; + + const filterOptions = useSelector((state) => state.sampleGrid.filterOptions); + + const pucks = useSelector((state) => state.sampleChanger.contents.children); + + const cellID = 1; + + const dispatch = useDispatch(); + + function handleClickOnCellPuck(event, puckID) { + dispatch( + filterAction({ cellFilter: `${cellID}`, puckFilter: `${puckID}` }), + ); + event.stopPropagation(); + } + + useEffect(() => { + if (filterOptions.cellFilter === '') { + dispatch(filterAction({ cellFilter: '1', puckFilter: '1' })); + } + }, [filterOptions.cellFilter, dispatch]); + + function handleDisplayPuckCellContextMenu(e, menuID, puckID) { + e.preventDefault(); + handleClickOnCellPuck(e, cellID, puckID === null ? '' : puckID); + displayPuckCellContextMenu(e, menuID, cellID, puckID); + e.stopPropagation(); + } + + function getSingleCellAsCircle(centerX, centerY) { + const totalPucks = pucks.length; + + // Adjust angle range based on puck count + const useFullCircle = totalPucks >= 8; + const angleRange = useFullCircle ? 2 * Math.PI : Math.PI * 1.5; + const startAngle = useFullCircle ? 0 : (Math.PI - angleRange) / 2; + + // Circle size and spacing + const baseRadius = 4; + const placementRadius = baseRadius + Math.max(0, (totalPucks - 16) * 0.3); + const puckRadius = Math.min( + 0.7, + (2 * Math.PI * placementRadius) / (totalPucks * 2), + ); + + // Fix angle spacing: avoid skipping puck 1 or overlapping at end + const angleDivisor = useFullCircle + ? totalPucks + : Math.max(1, totalPucks - 1); + + return pucks.map((_, i) => { + const angle = startAngle + (angleRange * i) / angleDivisor; + const x = centerX + placementRadius * Math.cos(angle); + const y = centerY + placementRadius * Math.sin(angle); + const puckID = i + 1; + + const isPuckSelected = + Number(filterOptions.cellFilter) === cellID && + Number(filterOptions.puckFilter) === puckID; + + return ( + handleClickOnCellPuck(e, puckID)} + onContextMenu={(e) => + handleDisplayPuckCellContextMenu(e, puckMenuID, puckID) + } + fill={isPuckSelected ? '#015f9d' : '#cdced1'} + className="puck_cicle" + > + + + Puck {puckID} + + + Cell: {cellID}, Puck: {puckID} + + + ); + }); + } + + return ( + +
+ + + {getSingleCellAsCircle(10, 10)} + + {type} + + +
+ + ); +} diff --git a/ui/src/containers/SampleGridTableContainer.jsx b/ui/src/containers/SampleGridTableContainer.jsx index 1cc06334d..95dc6d25d 100644 --- a/ui/src/containers/SampleGridTableContainer.jsx +++ b/ui/src/containers/SampleGridTableContainer.jsx @@ -29,6 +29,7 @@ import { } from '../actions/sampleGrid'; import { showTaskForm } from '../actions/taskForm'; import MXContextMenu from '../components/GenericContextMenu/MXContextMenu'; +import SampleCircleView from '../components/SampleGrid/SampleCircleView'; import { SampleGridTableItem } from '../components/SampleGrid/SampleGridTableItem'; import { TaskItem } from '../components/SampleGrid/TaskItem'; import TooltipTrigger from '../components/TooltipTrigger'; @@ -967,11 +968,15 @@ export default function SampleGridTableContainer(props) { } function getSampleListAsDrawing() { - if (type.includes('CATS')) { + const isCATS = type.includes('CATS'); + const isFLEX = type.includes('FLEX'); + const isMOCK = type.includes('Mock'); + + if (isCATS) { return ; } - if (type.includes('FLEX') || type.includes('Moc')) { + if (isFLEX) { return ( ); } + if (isSingleCell || isMOCK) { + return ( + + ); + } + return null; } From 49ccd8e969c984ebc8e05dee9dca1e638a7562f3 Mon Sep 17 00:00:00 2001 From: FLorial Jean Baptiste Date: Wed, 7 May 2025 11:39:41 +0200 Subject: [PATCH 2/2] Turn isSingleCell into a variable to avoid having to invoke the function everywhere --- .../containers/SampleGridTableContainer.jsx | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/ui/src/containers/SampleGridTableContainer.jsx b/ui/src/containers/SampleGridTableContainer.jsx index 95dc6d25d..642952e75 100644 --- a/ui/src/containers/SampleGridTableContainer.jsx +++ b/ui/src/containers/SampleGridTableContainer.jsx @@ -130,8 +130,8 @@ function checkForOverlap(el1, el2) { } // Helper function to determine puck colsm value -function getColsm(singleCell, puckCount) { - if (singleCell) { +function getColsm(isSingleCell, puckCount) { + if (isSingleCell) { return puckCount <= 4 ? 3 : true; } return puckCount === 1 ? 2 : puckCount === 2 ? 4 : puckCount === 3 ? 6 : true; @@ -170,6 +170,10 @@ export default function SampleGridTableContainer(props) { const [rubberBandVisible, setRubberBandVisible] = useState(false); + const isSingleCell = Object.values(sampleList).every( + (sample) => sample.cell_no === 1 || sample.cell_no === 0, + ); + // this supose to replace old shouldComponentUpdate , not sure we need it useEffect(() => { console.log('Component Updated'); // eslint-disable-line no-console @@ -480,16 +484,10 @@ export default function SampleGridTableContainer(props) { e.stopPropagation(); } - function isSingleCell() { - return Object.values(sampleList).every( - (sample) => sample.cell_no === 1 || sample.cell_no === 0, - ); - } - function getSampleItemCollapsibleHeaderActions(cellID) { return (
- {isSingleCell() ? null : `Cell ${cellID}`} + {isSingleCell ? null : `Cell ${cellID}`} {sampleItemsControls(cellID, null)} { - const puckID = isSingleCell() ? Number(puck.name) : puckidx + 1; + const puckID = isSingleCell ? Number(puck.name) : puckidx + 1; const [filterList] = getSampleListFilteredByCellPuck(cellID, puckID); return ( @@ -682,7 +680,7 @@ export default function SampleGridTableContainer(props) { {puckList.map((puck) => { const puckidx = cell.children.findIndex((p) => p.name === puck.name); - const puckID = isSingleCell() ? Number(puck.name) : puckidx + 1; + const puckID = isSingleCell ? Number(puck.name) : puckidx + 1; return ( {puckList.map((puck) => { const puckidx = cell.children.findIndex((p) => p.name === puck.name); - const puckID = isSingleCell() ? Number(puck.name) : puckidx + 1; + const puckID = isSingleCell ? Number(puck.name) : puckidx + 1; return (