Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add zoom & rotate functionality to crash diagrams #1635

Merged
merged 53 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
e75b246
react zoom pan pinch lib
frankhereford Dec 19, 2024
6f901af
stub in some buttons to zoom and reset
frankhereford Dec 19, 2024
20861ef
rotate control component
frankhereford Dec 19, 2024
69980e2
hook rotation up to the reset button
frankhereford Dec 19, 2024
3780726
react icons
frankhereford Dec 19, 2024
7c0dd6c
rename component
frankhereford Dec 19, 2024
0e397b3
styling up the buttons
frankhereford Dec 19, 2024
bbd677e
sort of free-wheeling dialing in buttons?
frankhereford Dec 19, 2024
01daf72
this looks much more normal
frankhereford Dec 19, 2024
378e6c3
group your buttons with a button group
frankhereford Dec 19, 2024
139564f
pixel pushing
frankhereford Dec 20, 2024
99ac5c8
lay it out
frankhereford Dec 20, 2024
d80af9a
pixel pushing
frankhereford Dec 20, 2024
41bfa46
pixel pushing
frankhereford Dec 20, 2024
bd627da
move rotation control
frankhereford Dec 20, 2024
3d404c0
format rotation handle
frankhereford Dec 20, 2024
a8c5404
layout for image
frankhereford Dec 20, 2024
0b29c7c
Refine language to be less "it's your fault"
frankhereford Dec 20, 2024
11e2441
Push these down a little
frankhereford Dec 20, 2024
8953a58
Propose more direct message
frankhereford Dec 20, 2024
766d24e
order imports by convention
frankhereford Dec 20, 2024
3eea054
whitespace
frankhereford Dec 20, 2024
e2a513d
tool tip and accessability
frankhereford Dec 20, 2024
df439e8
whitespace is free
frankhereford Dec 20, 2024
427eab1
a constant string
frankhereford Dec 20, 2024
a0e6341
fuss with image sizing
frankhereford Dec 20, 2024
2228e21
more whitespace
frankhereford Dec 20, 2024
a0cb2cc
drop div in lieu of buttongroup
frankhereford Dec 20, 2024
396e281
adopt zoom iconography
frankhereford Dec 20, 2024
ae3eaa2
fix vertical scroll bar
frankhereford Dec 20, 2024
6f84885
use bootstrap utility class
frankhereford Dec 20, 2024
1e533c6
Use bootstrap range control
frankhereford Dec 20, 2024
7606df2
use bootstrap utility
frankhereford Dec 20, 2024
584d84f
Match buttons to the rest of the app
frankhereford Dec 20, 2024
75836cd
woops forgot to remove my hardcoded style
frankhereford Dec 20, 2024
725f2f5
unused classname
frankhereford Dec 20, 2024
22fef34
Merge branch 'nextjs' into frank/diagram-gizmos
johnclary Dec 23, 2024
396bea4
Incorporate John's JSX
frankhereford Jan 14, 2025
e3b8184
moving the alert into its own component
frankhereford Jan 14, 2025
914f1b7
incorporate the new alert component
frankhereford Jan 14, 2025
d57995c
remove labels
frankhereford Jan 14, 2025
622d59f
details for the rotation handle
frankhereford Jan 14, 2025
f6890d7
get a little space in there
frankhereford Jan 14, 2025
5126211
Merge branch 'nextjs' into frank/diagram-gizmos
frankhereford Jan 14, 2025
a59b40e
updated lock file
frankhereford Jan 14, 2025
229401d
remove unused import
frankhereford Jan 14, 2025
fcb216e
minscale
frankhereford Jan 15, 2025
43ef540
zoom step size
frankhereford Jan 15, 2025
ff554b8
check this in before i try something else
frankhereford Jan 22, 2025
0e78ab6
rework this to include a function that zooms the image to fit into th…
frankhereford Jan 22, 2025
e4e08cd
use the new function for the reset button too
frankhereford Jan 22, 2025
996f43d
use secondary text color
frankhereford Jan 22, 2025
c976f68
h/t @johnclary: set animation duration to 1 ms with no customScale
frankhereford Jan 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 143 additions & 45 deletions app/components/CrashDiagramCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,63 +2,161 @@ import { useState } from "react";
import Alert from "react-bootstrap/Alert";
import Card from "react-bootstrap/Card";
import Image from "react-bootstrap/Image";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import ButtonGroup from "react-bootstrap/ButtonGroup";
import { FaMagnifyingGlassPlus, FaMagnifyingGlassMinus } from "react-icons/fa6";
import { SlActionUndo } from "react-icons/sl";
import {
TransformWrapper,
TransformComponent,
useControls,
} from "react-zoom-pan-pinch";
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
import AlignedLabel from "@/components/AlignedLabel";
import { Crash } from "@/types/crashes";

// import axios from "axios";
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
// import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";

const CR3_DIAGRAM_BASE_URL = process.env.NEXT_PUBLIC_CR3_DIAGRAM_BASE_URL!;

frankhereford marked this conversation as resolved.
Show resolved Hide resolved
const ZoomResetControls = ({
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
setRotation,
}: {
setRotation: (value: number) => void;
}) => {
const { zoomIn, zoomOut, resetTransform } = useControls();

const handleReset = () => {
resetTransform();
setRotation(0);
};

return (
<div className="d-flex justify-content-between w-100 mb-1">
<ButtonGroup>
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
<Button
size="sm"
variant="primary"
onClick={() => zoomIn()}
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
title="Zoom In"
>
<AlignedLabel>
<FaMagnifyingGlassPlus className="me-2" />
<span>Zoom In</span>
</AlignedLabel>
</Button>
<Button
size="sm"
variant="primary"
onClick={() => zoomOut()}
title="Zoom Out"
>
<AlignedLabel>
<FaMagnifyingGlassMinus className="me-2" />
<span>Zoom Out</span>
</AlignedLabel>
</Button>
</ButtonGroup>
<Button size="sm" variant="primary" onClick={handleReset} title="Reset">
<AlignedLabel>
<SlActionUndo className="me-2" />
<span>Reset</span>
</AlignedLabel>
</Button>
</div>
);
};

const RotateControls = ({
rotation,
setRotation,
}: {
rotation: number;
setRotation: (value: number) => void;
}) => {
const rotate = (event: React.ChangeEvent<HTMLInputElement>) => {
setRotation(Number(event.target.value));
};
frankhereford marked this conversation as resolved.
Show resolved Hide resolved

return (
<div className="mt-2">
<Form.Range
min="-180"
max="180"
value={rotation}
id="formControlRange"
onChange={rotate}
style={{ width: "70%" }}
title="Rotate Diagram"
/>
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
</div>
);
};

export default function CrashDiagramCard({ crash }: { crash: Crash }) {
const [diagramError, setDiagramError] = useState(false);
const [rotation, setRotation] = useState(0);

return (
<Card>
<Card.Header>Diagram</Card.Header>
<Card.Body className="crash-header-card-body text-center">
{!diagramError && (
<Image
fluid
style={{
height: "100%",
maxWidth: "100%",
}}
src={`${CR3_DIAGRAM_BASE_URL}/${crash.record_locator}.jpeg`}
alt="crash diagram"
onError={() => {
console.error("Error loading CR3 diagram image");
setDiagramError(true);
}}
/>
)}
{diagramError && crash.is_temp_record && (
<Alert variant="info">
<i className="fa fa-info-circle" /> Crash diagrams are not available
for user-created crash records
</Alert>
)}
{diagramError && !crash.is_temp_record && (
<Alert variant="danger">
<p>
The crash diagram is not available. Typically, this indicates
there was an error when processing this crash&aposs CR3 PDF.
</p>
<p>
For additional assistance, you can&nbsp;
<a
href="https://atd.knack.com/dts#new-service-request/?view_249_vars=%7B%22field_398%22%3A%22Bug%20Report%20%E2%80%94%20Something%20is%20not%20working%22%2C%22field_399%22%3A%22Vision%20Zero%20Editor%22%7D"
target="_blank"
rel="noopener noreferrer"
>
report a bug
<i className="fa fa-external-link"></i>
</a>
.
</p>
</Alert>
)}
<TransformWrapper initialScale={1}>
{!diagramError && <ZoomResetControls setRotation={setRotation} />}
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
<TransformComponent>
<div style={{ height: "330px", width: "100%", overflow: "hidden" }}>
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
{!diagramError && (
<Image
fluid
style={{
height: "100%",
width: "440px",
transform: `rotate(${rotation}deg)`,
objectFit: "contain",
}}
src={`${CR3_DIAGRAM_BASE_URL}/${crash.record_locator}.jpeg`}
alt="crash diagram"
onError={() => {
console.error("Error loading CR3 diagram image");
setDiagramError(true);
}}
/>
)}
{diagramError && crash.is_temp_record && (
<div
className="d-flex align-items-start justify-content-center h-100 mt-3"
style={{ width: "490px" }}
>
<Alert variant="info" className="mx-auto">
<i className="fa fa-info-circle" />
Crash diagrams are not available for temporary crash records
</Alert>
</div>
)}
{diagramError && !crash.is_temp_record && (
<Alert variant="danger" style={{ marginTop: "20px" }}>
<p>The crash diagram is not available.</p>
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
<p>
For additional assistance, you can&nbsp;
<a
href="https://atd.knack.com/dts#new-service-request/?view_249_vars=%7B%22field_398%22%3A%22Bug%20Report%20%E2%80%94%20Something%20is%20not%20working%22%2C%22field_399%22%3A%22Vision%20Zero%20Editor%22%7D"
target="_blank"
rel="noopener noreferrer"
>
report a bug
<i className="fa fa-external-link"></i>
</a>
.
</p>
</Alert>
)}
</div>
</TransformComponent>
</TransformWrapper>
</Card.Body>
<Card.Footer>Something else here</Card.Footer>
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
{!diagramError && (
<Card.Footer className="text-center">
<RotateControls rotation={rotation} setRotation={setRotation} />
</Card.Footer>
)}
</Card>
);
}
23 changes: 19 additions & 4 deletions app/package-lock.json
frankhereford marked this conversation as resolved.
Show resolved Hide resolved

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

3 changes: 2 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
"react-datepicker": "^7.5.0",
"react-dom": "^18",
"react-hook-form": "^7.53.2",
"react-icons": "^5.3.0",
"react-icons": "^5.4.0",
frankhereford marked this conversation as resolved.
Show resolved Hide resolved
"react-map-gl": "^7.1.7",
"react-zoom-pan-pinch": "^3.6.1",
"swr": "^2.2.5"
},
"devDependencies": {
Expand Down