Skip to content

Commit

Permalink
moved photo component to separate file #2
Browse files Browse the repository at this point in the history
  • Loading branch information
hcwinsemius committed Jan 24, 2025
1 parent feb29c6 commit aff580a
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 138 deletions.
1 change: 1 addition & 0 deletions dashboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ npm install react-router-dom # for organizing the router
npm install dotenv # for setting environment variables
npm install react-icons
npm install react-zoom-pan-pinch
npm install react-draggable

# Start dev server, ensuring the API url is added as environment variable
VITE_API_BASE_URL="http://<name-of-server>:<port-of-server>" npm run dev
Expand Down
27 changes: 24 additions & 3 deletions dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"leaflet": "^1.9.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-draggable": "^4.4.6",
"react-icons": "^5.4.0",
"react-leaflet": "^4.2.1",
"react-router-dom": "^7.1.1",
Expand Down
40 changes: 21 additions & 19 deletions dashboard/src/views/calibration.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import ControlPointsTab from './calibrationTabs/controlPointsTab'
import VideoTab from './calibrationTabs/videoTab'
import './calibration.css'; // Ensure the styles reflect the updated layout.

const Calibration = () => {
Expand Down Expand Up @@ -29,6 +29,8 @@ const Calibration = () => {

return (
<div className="tabbed-form-container">
<h1>Camera calibration</h1>

{/* Form container */}
<form onSubmit={handleSubmit} className="tabbed-layout">
{/* Tabs column */}
Expand All @@ -40,51 +42,51 @@ const Calibration = () => {
handleTabChange('video');
}}
>
Video
Video view
</button>
<button
className={activeTab === 'controlPoints' ? 'active-tab' : ''}
className={activeTab === 'threed' ? 'active-tab' : ''}
onClick={(e) => {
e.preventDefault();
handleTabChange('controlPoints');
handleTabChange('threed');
}}
>
Control Points
3D View
</button>
<button
className={activeTab === 'recipe' ? 'active-tab' : ''}
className={activeTab === 'map' ? 'active-tab' : ''}
onClick={(e) => {
e.preventDefault();
handleTabChange('recipe');
handleTabChange('map');
}}
>
Recipe
Map View
</button>
</div>

{/* Tab content */}
<div className="tab-content">
{activeTab === 'video' && (
<VideoTab
/>
)}
{activeTab === 'threed' && (
<div>
<label>Video URL</label>
<label>3D view</label>
<input
type="text"
value={formData.video}
onChange={(e) => handleInputChange('video', e.target.value)}
value={formData.threed}
onChange={(e) => handleInputChange('threed', e.target.value)}
/>
</div>
)}
{activeTab === 'controlPoints' && (
<ControlPointsTab
/>
)}
{activeTab === 'recipe' && (
{activeTab === 'map' && (
<div>
<label>Recipe Details</label>
<label>Map view</label>
<textarea
value={formData.recipe}
value={formData.map}
onChange={(e) =>
handleInputChange('recipe', e.target.value)
handleInputChange('map', e.target.value)
}
></textarea>
</div>
Expand Down
49 changes: 26 additions & 23 deletions dashboard/src/views/calibrationTabs/XyzWidget.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,63 @@ const XYZWidget = ({ id, coordinates, onUpdate, onDelete }) => {

return (
<div className="widget">
<div style={{ display: 'flex', gap: '10px' }}>
<div style={{ marginTop: '5px', display: 'flex', gap: '15px' }}>
<label>
X:
row:
<input
type="number"
name="x"
value={coordinates.x || ''}
name="row"
step="1"
value={coordinates.row || ''}
onChange={handleChange}
disabled
/>
</label>
<label>
Y:
column:
<input
type="number"
name="y"
value={coordinates.y || ''}
name="col"
step="1"
value={coordinates.col || ''}
onChange={handleChange}
disabled
/>
</label>
<button className="close-button" onClick={handleDelete}>
&times;
</button>
</div>
<div style={{ display: 'flex', gap: '5px', marginTop: '0px'}}>
<label>
Z:
X:
<input
type="number"
name="z"
value={coordinates.z || ''}
name="x"
value={coordinates.x || ''}
onChange={handleChange}
/>
</label>
</div>
<div style={{ marginTop: '10px', display: 'flex', gap: '10px' }}>
<label>
row:
Y:
<input
type="number"
name="row"
step="1"
value={coordinates.row || ''}
name="y"
value={coordinates.y || ''}
onChange={handleChange}
/>
</label>
<label>
column:
Z:
<input
type="number"
name="col"
step="1"
value={coordinates.col || ''}
name="z"
value={coordinates.z || ''}
onChange={handleChange}
/>
</label>
<button className="close-button" onClick={handleDelete}>
&times;
</button>
</div>

</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,9 @@
import React, { useState, useRef, useEffect } from 'react';
import { TransformWrapper, TransformComponent, useTransformContext, useTransformEffect, useTransformInit } from 'react-zoom-pan-pinch';
import XYZWidget from './XyzWidget';
import React, { useState, useRef } from 'react';
import { TransformComponent, useTransformEffect, useTransformInit } from 'react-zoom-pan-pinch';

const ControlPointsTab = () => {
const [widgets, setWidgets] = useState([]);
const [nextId, setNextId] = useState(1); // widget ids increment automatically
const [selectedWidgetId, setSelectedWidgetId] = useState(null); // To track which widget is being updated
const [dots, setDots] = useState([]); // Array of { x, y, id } objects
const imageRef = useRef(null); // Reference to image within TransFormWrapper

const addWidget = () => {
setWidgets((prevWidgets) => [
...prevWidgets,
{ id: nextId, coordinates: { x: '', y: '', z: '', row: '', col: '' } },
]);
setNextId((prevId) => prevId + 1); // increment the unique id for the next widget

};

const updateWidget = (id, updatedCoordinates) => {
setWidgets((prevWidgets) =>
prevWidgets.map((widget) =>
widget.id === id ? { ...widget, coordinates: updatedCoordinates } : widget
)
);
};

const deleteWidget = (id) => {
setWidgets((prevWidgets) => prevWidgets.filter((widget) => widget.id !== id));
// also delete the dot
};

const HandlePhotoClickContext = () => {
const PhotoComponent = ({imageRef, selectedWidgetId, updateWidget, widgets, scale}) => {
const [transformState, setTransformState] = useState(null); // state of zoom is stored here
const [dots, setDots] = useState([]); // Array of { x, y, id } objects

useTransformInit(({state, instance}) => {
// ensure the zoom/pan state is stored in a react state at the mounting of the photo element
Expand All @@ -44,7 +15,6 @@ const HandlePhotoClickContext = () => {
});

const handlePhotoClick = (event) => {
// console.log(transformState);
event.stopPropagation();
if (!transformState) {
console.error("TransformContext state is null or uninitialized");
Expand Down Expand Up @@ -85,7 +55,7 @@ const HandlePhotoClickContext = () => {
// Update the dots
setDots((prevDots) => ({
...prevDots,
[selectedWidgetId]: { x: adjustedX, y: adjustedY },
[selectedWidgetId]: { x: adjustedX, y: adjustedY, scale: scale },
}));

updateWidget(selectedWidgetId, {
Expand Down Expand Up @@ -116,16 +86,16 @@ const HandlePhotoClickContext = () => {
top: `${dot.y}px`,
left: `${dot.x}px`,
transform: "translate(-50%, -50%)",
width: "20px",
height: "20px",
width: `${20 / scale}px`,
height: `${20 / scale}px`,
backgroundColor: "red", // Change color as needed
borderRadius: "50%",
transform: "translate(-50%, -50%)", // Center the dot
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "#fff",
fontSize: "8px",
fontSize: `${10 / scale}px`,
fontWeight: "bold",
}}
>
Expand All @@ -136,53 +106,4 @@ const HandlePhotoClickContext = () => {
</TransformComponent>
);
};

return (
<div>
<h1>Camera calibration</h1>
<div style={{ display: 'flex', margin: '20px' }}>
<div style={{ flex: 1, border: '1px solid black', marginRight: '20px', position: 'relative' }}>
<TransformWrapper>
<HandlePhotoClickContext
selectedWidgetId={selectedWidgetId}
setDots={setDots}
setWidgets={setWidgets}
/>
</TransformWrapper>
<div style={{ textAlign: 'center', marginTop: '10px', color: '#555' }}>
Click on the photo to select row/column
</div>
</div>
<div>
<div style={{ flex: 1 }}>
<button onClick={addWidget} className="btn">Add Widget</button>
{widgets.map((widget) => (
<div key={widget.id} onClick={(event) =>
setSelectedWidgetId(widget.id)
}
style={{
border: selectedWidgetId === widget.id ? '4px solid red' : '1px solid black',
marginBottom: '10px',
padding: '10px',
color: 'white',
cursor: 'pointer',
}}
>
<XYZWidget
id={widget.id}
coordinates={widget.coordinates}
onUpdate={(id, coordinates) => updateWidget(id, coordinates)}
onDelete={deleteWidget}
/>
</div>
))}
</div>
</div>
</div>
<h2>Current Coordinates:</h2>
<pre>{JSON.stringify(widgets, null, 2)}</pre>
</div>
);
};

export default ControlPointsTab;
export default PhotoComponent;
Loading

0 comments on commit aff580a

Please sign in to comment.