Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
242 commits
Select commit Hold shift + click to select a range
dfea224
add annotate mode to modal sidebar
benjaminpkane Jun 24, 2025
cc3e618
linting
benjaminpkane Jun 24, 2025
077d66f
organizing sidebar
benjaminpkane Jul 1, 2025
4f18d95
entries work
benjaminpkane Jul 2, 2025
5c70b14
linting
benjaminpkane Jul 8, 2025
a78c692
sidebar entry work
benjaminpkane Jul 18, 2025
4640911
import schema layout
benjaminpkane Jul 18, 2025
33828e4
annotation schema prototype and tests
benjaminpkane Jul 30, 2025
9225f22
Update fiftyone/core/annotation.py
benjaminpkane Jul 30, 2025
f3a0efa
linting
benjaminpkane Jul 30, 2025
bc8bc22
Merge branch 'label-schema-tests' of github.com:voxel51/fiftyone into…
benjaminpkane Jul 30, 2025
c56422e
schema manager pages
benjaminpkane Aug 11, 2025
3dc59d7
schema manager pages
benjaminpkane Aug 18, 2025
75cba84
docs lint
benjaminpkane Aug 19, 2025
acd5ad4
Merge branch 'import-schema' into integrate-label-schemas
benjaminpkane Aug 19, 2025
76684d6
error handling feedback
benjaminpkane Aug 25, 2025
6e57b5c
Merge branch 'label-schema-tests' into integrate-label-schemas
benjaminpkane Aug 26, 2025
755400c
schema work
benjaminpkane Sep 4, 2025
2b4ab03
initialize lighter package with TypeScript configuration
sashankaryal Jun 25, 2025
6dcfcdc
add core type definitions for lighter package
sashankaryal Jun 25, 2025
690173b
implement core scene and event system
sashankaryal Jun 25, 2025
afda6d6
add overlay system with bounding box and classification support
sashankaryal Jun 25, 2025
3afb0a7
implement resource loading and rendering strategies
sashankaryal Jun 25, 2025
cf5e963
add undo/redo system and overlay factory
sashankaryal Jun 25, 2025
6236435
update yarn lockfile for lighter package dependencies
sashankaryal Jun 25, 2025
617d222
restructure package architecture with new Scene2D system
sashankaryal Jun 25, 2025
7f21696
add improved event bus system
sashankaryal Jun 25, 2025
78823c0
implement new overlay system with improved architecture
sashankaryal Jun 25, 2025
45cd810
add React integration with hooks-based API
sashankaryal Jun 25, 2025
554557e
implement PixiJS-based 2D rendering system
sashankaryal Jun 25, 2025
9149b68
add resource management, undo system, and plugin registry
sashankaryal Jun 25, 2025
134a660
add documentation, examples, and test setup
sashankaryal Jun 25, 2025
d2f85d4
update package configuration and modal integration
sashankaryal Jun 25, 2025
bd8d7eb
update yarn lockfile for restructured dependencies
sashankaryal Jun 25, 2025
1b9f5c9
add image overlay support for rendering images
sashankaryal Jun 25, 2025
34358c6
add rendering state management
sashankaryal Jun 25, 2025
23ecb0e
add React hooks for PixiJS integration
sashankaryal Jun 25, 2025
34b0c6d
add undo/redo commands for bounding box operations
sashankaryal Jun 25, 2025
87830c1
add server-side media route support
sashankaryal Jun 25, 2025
54d6a36
new readme
sashankaryal Jun 25, 2025
2c265fc
enhance core components with image rendering capabilities
sashankaryal Jun 25, 2025
d7c84ce
update yarn lockfile for image rendering dependencies
sashankaryal Jun 25, 2025
b7f4526
remove outdated examples and test files
sashankaryal Jun 25, 2025
88ab2c9
rename React components for better clarity
sashankaryal Jun 25, 2025
dadb7b2
add global PIXI resource loader
sashankaryal Jun 25, 2025
de7faa8
update core components and remove renderer dependencies
sashankaryal Jun 25, 2025
b549fc0
implement style passing from scene to overlays
sashankaryal Jun 25, 2025
4a33ef5
update yarn lockfile dependencies
sashankaryal Jun 25, 2025
1606a9d
event dispatch system wired
sashankaryal Jul 15, 2025
bd260fd
expose canvas
sashankaryal Jul 15, 2025
2b39b9b
implement coordinate transformation and canonical media
sashankaryal Jul 16, 2025
30113a5
add way to only update resource bounds
sashankaryal Jul 17, 2025
446995a
update relative bounds
sashankaryal Jul 17, 2025
e89764b
add architecture doc
sashankaryal Jul 17, 2025
2d7a39a
take selection maanger as explicit dep
sashankaryal Jul 17, 2025
b8b1c8d
simplify interaction manager and selection manager interactions
sashankaryal Jul 17, 2025
fb59a04
hook up with active paths
sashankaryal Jul 18, 2025
01b3e7b
simplify shouldShowOverlay
sashankaryal Jul 18, 2025
f93de5d
divide into read and write hooks
sashankaryal Jul 18, 2025
35e0639
allow injection of callbacks in render loop
sashankaryal Jul 18, 2025
62e1223
feature parity with looker on label selection
sashankaryal Aug 14, 2025
9d5dd61
fix 'manage selected' action from toolbar
sashankaryal Aug 14, 2025
edfd048
allow effects in session atoms
sashankaryal Aug 15, 2025
ccb2a66
two way binding for selection events
sashankaryal Aug 15, 2025
2ca058e
add bridge between fiftyone color and lighter color
sashankaryal Aug 15, 2025
0689fe8
basic tooltip impl
sashankaryal Aug 19, 2025
b587688
tooltip follows pointer and is off when dragging
sashankaryal Aug 20, 2025
4dc2424
more nuanced coordinate transformation for dragging vs hover
sashankaryal Aug 20, 2025
a01f1af
add dashed line for selection
sashankaryal Aug 25, 2025
6a30b01
mouse drag and pointer depending on interaction type
sashankaryal Aug 26, 2025
01b7630
upgrade pixi from 8.10 to 8.12
sashankaryal Aug 26, 2025
79012e7
more precise hit testing
sashankaryal Aug 26, 2025
668e547
same stroke width as looker
sashankaryal Aug 26, 2025
08be39c
match font
sashankaryal Aug 27, 2025
a1e59a6
implement occluded labels rotation
sashankaryal Sep 2, 2025
b3aa6c1
better occlusion controls
sashankaryal Sep 3, 2025
a0c807f
more idiomatic header returns
sashankaryal Sep 4, 2025
dde232b
only init pixi resource loader once
sashankaryal Sep 4, 2025
37e6900
better scene cleanup
sashankaryal Sep 4, 2025
f6f477c
don't return erroneously early before hooks
sashankaryal Sep 4, 2025
af8d059
improve readme
sashankaryal Sep 4, 2025
6934c86
remove extraneous props
sashankaryal Sep 4, 2025
9d08bf6
explicit naming for pixi renderer
sashankaryal Sep 4, 2025
3a2e4e7
make dispatch_DANGEROUSLY public API and promote executeCommand
sashankaryal Sep 4, 2025
99ccad5
make isUndoable optional
sashankaryal Sep 4, 2025
1509745
implement basic zoom and pan
sashankaryal Sep 4, 2025
750a9eb
remove decelerate in viewport
sashankaryal Sep 5, 2025
32cfb65
disable zoom and pan when dragging overlays
sashankaryal Sep 5, 2025
eecdb2b
reset cursor to default when no handler
sashankaryal Sep 5, 2025
0da5e37
event listener cleanup + better container management
sashankaryal Sep 6, 2025
3b478ff
stable canvas and max one webgl context
sashankaryal Sep 7, 2025
d67c8ea
merge
benjaminpkane Sep 9, 2025
90cc89e
only allow selection of one at any given point
sashankaryal Sep 10, 2025
79fde80
add transformOverlay command
sashankaryal Sep 10, 2025
6fa045b
Merge branch 'feat/lighter' into ha-integration
sashankaryal Sep 10, 2025
be33aed
add OVERLAY_BOUNDS_CHANGED event
sashankaryal Sep 10, 2025
b954a04
implement add detection, undo, redo in actions.tsx
sashankaryal Sep 10, 2025
29f622e
remove redundant commands
sashankaryal Sep 10, 2025
63bff3e
add overlay with undo/redo
sashankaryal Sep 10, 2025
fb66807
add hovering example, move label loading to jotai
benjaminpkane Sep 10, 2025
6bc8d71
make hovering more resilient on rotate labels
sashankaryal Sep 11, 2025
e72c8b9
persist modal mode in local storage
sashankaryal Sep 11, 2025
c6ca1c7
basic drag and create impl with interactive mode support
sashankaryal Sep 12, 2025
b6b2cdb
fix drag and create overlay
sashankaryal Sep 12, 2025
e0b5c67
add screenToWorld to account for viewport transformations
sashankaryal Sep 12, 2025
e929cd1
only use screen coordinates when interactive mode
sashankaryal Sep 12, 2025
2f5d6b6
add isOn prop for container styled-component
sashankaryal Sep 12, 2025
45a2a8a
two way binding for hover
sashankaryal Sep 12, 2025
88d36cd
refactor drag event handling to use absolute and relative bounds inst…
sashankaryal Sep 12, 2025
a2617da
strawman persistence for detections
sashankaryal Sep 12, 2025
b3be4a2
label form work
benjaminpkane Sep 12, 2025
dbf61f4
ask for label input in an interactive react form
sashankaryal Sep 22, 2025
d1cd561
implement label and field selection + remove overlay
sashankaryal Sep 22, 2025
3cffc3f
decouple lighter with core (1): move files to core
sashankaryal Sep 24, 2025
4e3f3cf
decouple lighter with core (2): simplify interactive detection handler
sashankaryal Sep 24, 2025
a0a4b13
rename to useOverlayPersistence
sashankaryal Sep 25, 2025
5bdeb78
FOEPD-1814: Annotation schema prototype (#6204)
benjaminpkane Oct 1, 2025
a93ea4f
ha work
benjaminpkane Oct 1, 2025
3d29073
Merge branch 'ha-integration' of github.com:voxel51/fiftyone into ha-…
benjaminpkane Oct 1, 2025
29dd031
merge
benjaminpkane Oct 1, 2025
c1a0344
implement basic annotation client
tom-vx51 Oct 1, 2025
11e533b
improve types
tom-vx51 Oct 1, 2025
6291177
update behavior to match server changes
tom-vx51 Oct 2, 2025
923eb37
remove unused import
tom-vx51 Oct 2, 2025
665ff7c
add static typing for event handlers
tom-vx51 Oct 2, 2025
09340a8
Merge pull request #6377 from voxel51/chore/lighter-event-typing
tom-vx51 Oct 2, 2025
f0ecc14
Feature/lighter gavin (#6376)
mcdoh Oct 3, 2025
d7f07ef
update to use getFetchFunction
tom-vx51 Oct 3, 2025
d5e41c5
fix request body
tom-vx51 Oct 3, 2025
bd111a6
add support for async error handlers
tom-vx51 Oct 3, 2025
7ade6bf
Account for scaling when zoomed (#6379)
mcdoh Oct 6, 2025
d1f714d
allow unspecified errors to pass through handler
tom-vx51 Oct 6, 2025
6d81b1f
Merge pull request #6372 from voxel51/feat/annotation-client
tom-vx51 Oct 6, 2025
8719903
Feature/scale text and lines (#6382)
mcdoh Oct 7, 2025
9fc5efe
merge develop
benjaminpkane Oct 7, 2025
e87673c
Lighter Tweaks (#6404)
mcdoh Oct 10, 2025
0cbabaa
Human Annotation Sidebar (#6410)
benjaminpkane Oct 13, 2025
5ee8b1f
Fix resource loader for full URLs (#6415)
benjaminpkane Oct 14, 2025
261a3aa
fix annotation schema tests
benjaminpkane Oct 14, 2025
2ad5f2a
Merge branch 'feat/human-annotation' of github.com:voxel51/fiftyone i…
benjaminpkane Oct 14, 2025
5ffeff0
Merge branch 'develop' into chore/merge-dev-20251014
tom-vx51 Oct 14, 2025
a7efa5e
Merge branch 'develop' into chore/merge-dev-20251014
tom-vx51 Oct 14, 2025
115036c
Merge pull request #6420 from voxel51/chore/merge-dev-20251014
benjaminpkane Oct 15, 2025
0a31d65
Human Annotation Readonly UX (#6417)
benjaminpkane Oct 15, 2025
14b06d6
Merge branch 'develop' into feat/human-annotation
benjaminpkane Oct 15, 2025
4cb3e66
Merge branch 'feat/human-annotation' of github.com:voxel51/fiftyone i…
benjaminpkane Oct 15, 2025
42c5a5c
Merge branch 'develop' into chore/merge-dev-20251015
tom-vx51 Oct 16, 2025
6d7df25
Merge pull request #6426 from voxel51/chore/merge-dev-20251015
benjaminpkane Oct 16, 2025
4491aae
include filter
benjaminpkane Oct 16, 2025
08223dd
Merge branch 'feat/human-annotation' of github.com:voxel51/fiftyone i…
benjaminpkane Oct 16, 2025
281b4d2
Merge pull request #6423 from voxel51/feature/establish-bounding-box
mcdoh Oct 16, 2025
ff883a7
undo/redo
Oct 16, 2025
536f200
integrate annotation experience with persistence endpoint
tom-vx51 Oct 15, 2025
a2ee608
add support for label deletion
tom-vx51 Oct 15, 2025
097b108
simplify version token management
tom-vx51 Oct 16, 2025
a65d2e5
add if-match to allowed cors headers; require if-match header for sam…
tom-vx51 Oct 16, 2025
7ecd2c1
fix version token format
tom-vx51 Oct 16, 2025
e96c227
Human Annotation sidebar cleanup (#6422)
benjaminpkane Oct 16, 2025
8da7f06
improve error handling
tom-vx51 Oct 16, 2025
5887e21
add transform controls for 3d labels
sashankaryal Sep 24, 2025
f6d9dda
show HUD while transforming
sashankaryal Sep 25, 2025
30a4cb6
refactor transform controls and labels files for maintainability
sashankaryal Sep 25, 2025
62d53d2
add polyline point markers in annotate mode
sashankaryal Sep 25, 2025
721acdf
add hover state for labels in annotate mode
sashankaryal Sep 25, 2025
782b8c3
separate annotate and transform modes
sashankaryal Sep 25, 2025
f9975c4
add annotation toolbar
sashankaryal Sep 26, 2025
336377e
disable scaling and rotation in polylines
sashankaryal Sep 26, 2025
ffe014a
add centroid marker
sashankaryal Sep 26, 2025
a10cd7e
use drei line for segments
sashankaryal Sep 26, 2025
31fc7fc
improve per-point transformation controls for polylines
sashankaryal Sep 26, 2025
8ea2b61
make annotation actions point transformation mode
sashankaryal Sep 26, 2025
155f207
implement point transformation HUD display
sashankaryal Sep 26, 2025
0f05338
impl moving of existing polyline points using point-specific transfor…
sashankaryal Sep 26, 2025
7b61a31
add coordinate input fields for point transformation
sashankaryal Sep 28, 2025
5779182
don't allow transformation on centroid
sashankaryal Sep 28, 2025
0371040
add event sourcing
sashankaryal Oct 1, 2025
adbf425
have a retry limit number for getBounds
sashankaryal Oct 7, 2025
fcb7349
basic multi-camera view rendering for anntoation
sashankaryal Oct 7, 2025
4438fcc
forward all camera refs to annotation views
sashankaryal Oct 7, 2025
827724d
forward default camera position
sashankaryal Oct 9, 2025
e96a2d8
implement polyline point transformations persisting across panels
sashankaryal Oct 10, 2025
482f315
add dedicated button to deselect annotation label
sashankaryal Oct 10, 2025
124f3fd
add basic segment polyline functionality
sashankaryal Oct 10, 2025
086d5bf
dynamic camera positions in side panels according to up vector
sashankaryal Oct 11, 2025
a87afa1
only show multi panel view when main 2d viewer is hidden
sashankaryal Oct 12, 2025
1818a00
show crosshair in side panel views too while annotating
sashankaryal Oct 12, 2025
63be1f4
add annotation plane functionality for z-drift protection
sashankaryal Oct 12, 2025
0169312
use perspective camera in main panel always
sashankaryal Oct 13, 2025
2a5f31c
make annotation plane responsive to up vector
sashankaryal Oct 13, 2025
ab34785
use distance based scaling for poly marker
sashankaryal Oct 13, 2025
f59392a
show segments in side panels too; move annotation related modules to …
sashankaryal Oct 13, 2025
84a99f4
universal transform controls
sashankaryal Oct 15, 2025
a81e309
use styled components
sashankaryal Oct 15, 2025
632c8d7
allow snapping to plane even when plane is toggled off from display
sashankaryal Oct 15, 2025
b01c79f
add feature to support automatic closure of polylines
sashankaryal Oct 15, 2025
cdc3616
convert temp segments into FO polylines
sashankaryal Oct 15, 2025
22da52d
simplify plane projection logic
sashankaryal Oct 15, 2025
8b49c22
allow net new polylines to be created
sashankaryal Oct 15, 2025
198656f
allow deleting vertices and implement segment merging logic
sashankaryal Oct 16, 2025
2cbb1e9
fix escape behavior
sashankaryal Oct 16, 2025
d9ca0bb
allow deleting entire polyline, too
sashankaryal Oct 16, 2025
d6660c3
add unit tests
sashankaryal Oct 16, 2025
76ab193
refactor annotation types; remove unused TransformHUD component
sashankaryal Oct 16, 2025
8e0928f
fix broken bounds test
sashankaryal Oct 16, 2025
7359ee5
address coderabbit PR comments
sashankaryal Oct 16, 2025
f02988b
prevent segment tearing when moving in-between vertices
sashankaryal Oct 16, 2025
8e99fba
break polyline into hooks
sashankaryal Oct 16, 2025
e3091a4
allow adding new vertices in middle of segments
sashankaryal Oct 16, 2025
7da715c
remove unused selector
sashankaryal Oct 16, 2025
7da5a11
show annotation sidebar for 3d datasets, too
sashankaryal Oct 16, 2025
c243877
calculate bounds only after scene load
sashankaryal Oct 16, 2025
3f8ff5b
filter labels in annotate mode by what's in annotation schema
sashankaryal Oct 16, 2025
b8c8003
fix crosshair bounds issue
sashankaryal Oct 16, 2025
14aa49c
prevent segment tearing from coordinate input, too
sashankaryal Oct 16, 2025
e3366d6
fix buggy transform controls
sashankaryal Oct 16, 2025
cf50c1e
Merge pull request #6427 from voxel51/feat/annotation-persistence
tom-vx51 Oct 17, 2025
90b1baa
more resilient bbox calculation
sashankaryal Oct 17, 2025
44709e0
add avoid-z-fighting global scene flag
sashankaryal Oct 17, 2025
14cf7a6
fix falsy check bug for minZ
sashankaryal Oct 17, 2025
3820e43
adjust scene bounds calculations
sashankaryal Oct 17, 2025
fd80182
add logic to refresh sample data after annotation save
tom-vx51 Oct 17, 2025
834cfd2
clean up logic
tom-vx51 Oct 17, 2025
fc0315a
deep clone mesh geometry to fix caching bug in multi-panel view
sashankaryal Oct 17, 2025
4d2c058
sync point and polyline transient transform status to other panels, too
sashankaryal Oct 17, 2025
74bdb06
update screenshots
sashankaryal Oct 17, 2025
05e5a67
compute delta using world matrices
sashankaryal Oct 17, 2025
313b05f
use skeleton cloning
sashankaryal Oct 17, 2025
12ea1f1
Merge pull request #6424 from voxel51/ha3d/mv
sashankaryal Oct 17, 2025
fb0d8f2
allow cursor in perpendicular plane
sashankaryal Oct 18, 2025
2edb3bd
add view shortcuts
sashankaryal Oct 19, 2025
54a6bf6
allow rotated annotation planes too
sashankaryal Oct 20, 2025
44848a0
default raycasting sensitivity to high
sashankaryal Oct 20, 2025
1c08ca6
update grid sample data on annotation response
tom-vx51 Oct 20, 2025
c4f5b66
fix stale unhover state when rotating through labels
sashankaryal Oct 20, 2025
61a07aa
dismiss tooltip if mousemove outside canvas bounds
sashankaryal Oct 20, 2025
d8103fd
fix tooltip ribbon color
sashankaryal Oct 20, 2025
35b5339
mark dirty in force enter / leave
sashankaryal Oct 20, 2025
30cdcf5
add getter and setter for field and label
sashankaryal Oct 20, 2025
641060b
Merge pull request #6445 from voxel51/fix/lighter-bugs
sashankaryal Oct 20, 2025
ed8ad75
add guard to prevent corrupting looker sample data
tom-vx51 Oct 20, 2025
d616a63
simplify scene creation
tom-vx51 Oct 20, 2025
6dd32fb
Merge pull request #6439 from voxel51/feat/ha-sample-refresh
tom-vx51 Oct 20, 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
6 changes: 3 additions & 3 deletions .github/workflows/build-docker-internal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
workflow_dispatch: {}
schedule:
# 4:05AM On Thursdays for vuln assessments.
- cron: '5 4 * * 4'
- cron: "5 4 * * 4"
jobs:
build-app:
uses: ./.github/workflows/build.yml
Expand All @@ -12,8 +12,8 @@ jobs:
runs-on: ubuntu-latest
needs: [build-app]
permissions:
contents: 'read'
id-token: 'write'
contents: "read"
id-token: "write"
strategy:
matrix:
python:
Expand Down
1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"packageManager": "[email protected]+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538",
"dependencies": {
"colormap": "^2.3.2",
"pixi-viewport": "^6.0.3",
"react-player": "^2.16.0",
"react-plotly.js": "^2.6.0"
},
Expand Down
1 change: 1 addition & 0 deletions app/packages/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<div id="modal"></div>
<div id="colorModal"></div>
<div id="queryPerformance"></div>
<div id="schemaManager"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions app/packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"jotai": "*",
"re-resizable": "*",
"react": "*",
"react-markdown": "*",
"react-relay": "*",
"recoil": "*",
"styled-components": "*"
Expand All @@ -48,8 +49,10 @@
"classnames": "^2.3.1",
"framer-motion": "^6.2.7",
"material-icons": "^1.13.12",
"re-resizable": "^6.9.17",
"react-input-autosize": "^3.0.0",
"react-laag": "^2.0.3",
"react-markdown": "^8.0.7",
"react-syntax-highlighter": "^15.5.0",
"react-use": "^17.5.1"
}
Expand Down
2 changes: 2 additions & 0 deletions app/packages/components/src/components/CodeBlock/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export default function CodeBlock({ text, ...props }: CodeBlockProps) {
return (
<Box
sx={{
width: "100%",
height: "100%",
position: "relative",
fontFamily: "Roboto Mono, monospace",
fontSize: props?.fontSize || 14,
Expand Down
1 change: 1 addition & 0 deletions app/packages/components/src/components/Loading/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default } from "./Loading";
export { default as LoadingDots } from "./LoadingDots";
export { default as LoadingSpinner } from "./LoadingSpinner";
10 changes: 5 additions & 5 deletions app/packages/components/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as CodeTabs } from "./CodeTabs";
export { default as ColoredDot } from "./ColoredDot";
export { default as CopyButton } from "./CopyButton";
export { default as Dialog } from "./Dialog";
export { default as EditableLabel } from "./EditableLabel";
export { default as ErrorBoundary, ErrorDisplayMarkup } from "./ErrorBoundary";
export { default as ExternalLink, useExternalLink } from "./ExternalLink";
export { default as FilterAndSelectionIndicator } from "./FilterAndSelectionIndicator";
Expand All @@ -19,10 +20,11 @@ export * from "./Icons";
export { default as JSONPanel } from "./JSONPanel";
export { default as JSONViewer } from "./JSONViewer";
export { default as Link } from "./Link";
export { default as Loading, LoadingDots } from "./Loading";
export { default as Loading, LoadingDots, LoadingSpinner } from "./Loading";
export { default as Markdown } from "./Markdown";
export { default as MuiButton } from "./MuiButton";
export { default as MuiIconFont } from "./MuiIconFont";
export { default as PanelCTA } from "./PanelCTA";
export { default as Pending } from "./Pending";
export { default as PillButton } from "./PillButton";
export { default as Popout, PopoutDiv } from "./Popout";
Expand All @@ -32,15 +34,13 @@ export { default as Resizable } from "./Resizable";
export * from "./Selection";
export { default as Selection } from "./Selection";
export { default as Selector, SelectorValidationError } from "./Selector";
export { default as StatusButton } from "./StatusButton";
export type { UseSearch } from "./Selector";
export { default as StatusButton } from "./StatusButton";
export { default as TabOption } from "./TabOption";
export { default as TextField } from "./TextField";
export { default as ThemeProvider, useFont, useTheme } from "./ThemeProvider";
export { default as Tooltip } from "./Tooltip";
export { default as Toast } from "./Toast";
export { default as PanelCTA } from "./PanelCTA";
export { default as EditableLabel } from "./EditableLabel";
export { default as Tooltip } from "./Tooltip";
export { default as TooltipProvider } from "./TooltipProvider";

export * from "./types";
4 changes: 3 additions & 1 deletion app/packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
"classnames": "^2.2.6",
"color": "^4.2.3",
"color-string": "^1.9.1",
"fast-json-patch": "^3.1.1",
"framer-motion": "^6.2.8",
"history": "^5.3.0",
"json-edit-react": "^1.28.2",
"lodash": "^4.17.21",
"lru-cache": "^11.0.1",
"luxon": "^3.6.1",
Expand Down Expand Up @@ -61,7 +63,7 @@
"@types/lodash": "^4.14.182",
"@types/luxon": "^3.6.2",
"@types/mime": "^2.0.3",
"@types/react": "^18.0.9",
"@types/react": "^18.2.0",
"@types/react-color": "^3.0.6",
"@types/react-dom": "^18.0.3",
"@types/react-grid-layout": "^1.3.5",
Expand Down
114 changes: 114 additions & 0 deletions app/packages/core/src/client/annotationClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Copyright 2017-2025, Voxel51, Inc.
*/

import { encodeURIPath, parseETag } from "./util";
import { Sample } from "@fiftyone/looker";
import {
FetchFunctionConfig,
FetchFunctionResult,
getFetchFunctionExtended,
MalformedRequestError,
NotFoundError,
} from "@fiftyone/utilities";
import * as jsonpatch from "fast-json-patch";

/**
* List of JSON-patch operation deltas between two versions of a json object.
*/
export type JSONDeltas = jsonpatch.Operation[];

export type PatchSampleRequest = {
datasetId: string;
sampleId: string;
deltas: JSONDeltas;
versionToken: string;
path?: string;
labelId?: string;
};

export type ErrorResponse = {
errors: string[];
};

export type PatchSampleResponse = {
sample: Sample;
versionToken: string;
};

/**
* Error resulting from a failed update operation.
*/
export class PatchApplicationError extends Error {
constructor(message?: string) {
super(message);
this.name = "Patch Application Error";
}
}

const handleErrorResponse = async (response: Response) => {
if (response.status === 400) {
// either a malformed request, or a list of errors from applying the patch
let errorResponse: ErrorResponse | undefined;
try {
// expected error response: '["error 1","error 2"]'
const body = await response.text();
const errorList = JSON.parse(body);
if (Array.isArray(errorList)) {
errorResponse = { errors: errorList };
}
} catch (err) {
// doesn't look like a list of errors
}
if (errorResponse?.errors) {
throw new PatchApplicationError(errorResponse.errors.join(", "));
}

throw new MalformedRequestError();
} else if (response.status === 404) {
throw new NotFoundError({ path: "sample" });
}
};

/**
* `fetch` with headers, error handling, etc.
*
* @param config fetch configuration
*/
const doFetch = <A, R>(
config: FetchFunctionConfig<A>
): Promise<FetchFunctionResult<R>> => {
return getFetchFunctionExtended()({
errorHandler: handleErrorResponse,
...config,
});
};

/**
* Patch a sample, applying the specified updates to its fields.
*
* @param request Patch sample request
*/
export const patchSample = async (
request: PatchSampleRequest
): Promise<PatchSampleResponse> => {
const pathParts = ["dataset", request.datasetId, "sample", request.sampleId];
if (request.path && request.labelId) {
pathParts.push(request.path, request.labelId);
}

const response = await doFetch<JSONDeltas, Sample>({
path: encodeURIPath(pathParts),
method: "PATCH",
body: request.deltas,
headers: {
"Content-Type": "application/json-patch+json",
"If-Match": `"${request.versionToken}"`,
},
});

return {
sample: response.response,
versionToken: parseETag(response.headers.get("ETag")),
};
};
1 change: 1 addition & 0 deletions app/packages/core/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./annotationClient";
95 changes: 95 additions & 0 deletions app/packages/core/src/client/transformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Copyright 2017-2025, Voxel51, Inc.
*/

import * as _ from "lodash";
import { isObject } from "./util";

/**
* DataTransformer implementations offer conversion from one record type to another.
*/
export type DataTransformer = {
transform: (data: Record<string, unknown>) => Record<string, unknown>;
};

/**
* FieldTransformer implementations offer conversion for a specific field type.
*/
export type FieldTransformer = {
canTransform: (data: unknown) => boolean;
transform: (data: unknown) => unknown;
};

/**
* Convert serialized python datetime.datetime data to a format consistent with
* graphql.
*/
const DateTimeTransformer: FieldTransformer = {
canTransform: (data: unknown): boolean => {
return isObject(data) && "$date" in (data as object);
},
transform: (data: unknown): { _cls: "DateTime"; datetime: number } => {
const date = new Date((data as { $date: string }).$date);
return { _cls: "DateTime", datetime: date.getTime() };
},
};

/**
* Convert serialized bson.ObjectId data to a format consistent with graphql.
*/
const ObjectIdTransformer: FieldTransformer = {
canTransform: (data: unknown): boolean => {
return isObject(data) && "$oid" in (data as object);
},
transform: (data: unknown): string => {
return (data as { $oid: string }).$oid;
},
};

const fieldTransformers = [DateTimeTransformer, ObjectIdTransformer];

/**
* Transformer which converts `fo.Sample.to_dict()` serialization to a format
* consistent with graphql.
*/
const SampleTransformer: DataTransformer = {
transform: (data: Record<string, unknown>): Record<string, unknown> => {
// recursive helper function
const transformInner = (innerData: unknown): unknown => {
// try to use a registered transformer
for (const transformer of fieldTransformers) {
if (transformer.canTransform(innerData)) {
return transformer.transform(innerData);
}
}

// otherwise recursively transform
if (Array.isArray(innerData)) {
return innerData.map((e) => transformInner(e));
} else if (isObject(innerData)) {
for (const key of Object.keys(innerData)) {
innerData[key] = transformInner(innerData[key]);
}
}

return innerData;
};

// transformation happens in-place, so create a new copy of the data first
const result = _.cloneDeep(data);
transformInner(result);
return result;
},
};

/**
* Transform sample data returned by `fo.Sample.to_dict()` to a format
* compatible with graphql query results.
*
* @param sample Serialized sample data
*/
export const transformSampleData = (
sample: Record<string, unknown>
): Record<string, unknown> => {
return SampleTransformer.transform(sample);
};
Loading
Loading