Skip to content

feat: OPTIC-1643: Copy Data Manager Quick View link to annotation or region #7122

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

Merged
merged 21 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5fb7b2f
feat: OPTIC-1643: Copy Data Manager Quick View link to annotation or …
bmartel Feb 20, 2025
bafe3c1
Adding copyText action and toast notification on successful copy of a…
bmartel Feb 20, 2025
7819557
linting
bmartel Feb 20, 2025
0aabeb5
adding new action to interfaces
bmartel Feb 20, 2025
56eb6eb
Merge remote-tracking branch 'origin/develop' into fb-optic-1643
bmartel Feb 20, 2025
abc41bb
Adding region context menu
bmartel Feb 20, 2025
10b8891
refactor region context menu to its own file
bmartel Feb 20, 2025
96ceb9f
linting
bmartel Feb 20, 2025
b1fcdbb
Only show annotation and region copy link options if the interface is…
bmartel Feb 21, 2025
610be27
Merge remote-tracking branch 'origin/develop' into fb-optic-1643
bmartel Feb 21, 2025
80a0129
use cn instead of hardcoding prefixes
bmartel Feb 21, 2025
f8659d8
fix imports
bmartel Feb 21, 2025
08f7be6
fix classNames
bmartel Feb 21, 2025
380d835
Merge branch 'develop' into 'fb-optic-1643'
MihajloHoma Feb 24, 2025
cdc9e85
Merge remote-tracking branch 'origin/develop' into fb-optic-1643
bmartel Feb 24, 2025
46489c3
ensure the annotation is persisted for the region context menu to be …
bmartel Feb 24, 2025
0ca4b45
add core to editor jest conf
bmartel Feb 24, 2025
effadc5
fix tests
bmartel Feb 24, 2025
0e4b330
allow predictions to be deep linked as well as annotations
bmartel Feb 24, 2025
7e86f26
ensure the annotationStore exists before using
bmartel Feb 24, 2025
04e2619
Merge branch 'develop' into 'fb-optic-1643'
MihajloHoma Feb 25, 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
24 changes: 19 additions & 5 deletions web/libs/datamanager/src/sdk/lsf-sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
FF_DEV_3034,
FF_LSDV_4620_3_ML,
FF_OPTIC_2,
FF_REGION_VISIBILITY_FROM_URL,
isFF,
} from "../utils/feature-flags";
import { isDefined } from "../utils/utils";
Expand Down Expand Up @@ -140,6 +141,9 @@ export class LSFWrapper {
"annotations:tabs",
"predictions:tabs",
);
if (isFF(FF_REGION_VISIBILITY_FROM_URL)) {
interfaces.push("annotations:copy-link");
}
}

if (this.datamanager.hasInterface("instruction")) {
Expand Down Expand Up @@ -345,7 +349,7 @@ export class LSFWrapper {
this.setLSFTask(task, annotationID, fromHistory);
}

setLSFTask(task, annotationID, fromHistory) {
setLSFTask(task, annotationID, fromHistory, selectPrediction = false) {
if (!this.lsf) return;

const hasChangedTasks = this.lsf?.task?.id !== task?.id && task?.id;
Expand Down Expand Up @@ -390,12 +394,12 @@ export class LSFWrapper {
this.lsf.toggleInterface("topbar:task-counter", true);
this.lsf.assignTask(task);
this.lsf.initializeStore(lsfTask);
this.setAnnotation(annotationID, fromHistory || isRejectedQueue);
this.setAnnotation(annotationID, fromHistory || isRejectedQueue, selectPrediction);
this.setLoading(false);
}

/** @private */
setAnnotation(annotationID, selectAnnotation = false) {
setAnnotation(annotationID, selectAnnotation = false, selectPrediction = false) {
const id = annotationID ? annotationID.toString() : null;
const { annotationStore: cs } = this.lsf;
let annotation;
Expand Down Expand Up @@ -459,7 +463,10 @@ export class LSFWrapper {
annotation = cs.createAnnotation();
}
} else {
if (this.annotations.length === 0 && this.predictions.length > 0 && !this.isInteractivePreannotations) {
if (selectPrediction) {
annotation = this.predictions.find((p) => p.pk === id);
annotation ??= first; // if prediction not found, select first annotation and resume existing behaviour
} else if (this.annotations.length === 0 && this.predictions.length > 0 && !this.isInteractivePreannotations) {
const predictionByModelVersion = this.predictions.find((p) => p.createdBy === this.project.model_version);
annotation = cs.addAnnotationFromPrediction(predictionByModelVersion ?? this.predictions[0]);
} else if (this.annotations.length > 0 && id && id !== "auto") {
Expand All @@ -472,7 +479,14 @@ export class LSFWrapper {
}

if (annotation) {
cs.selectAnnotation(annotation.id);
// We want to be sure this is explicitly understood to be a prediction and the
// user wants to select it directly
if (selectPrediction && annotation.type === "prediction") {
cs.selectPrediction(annotation.id);
} else {
// Otherwise we default the behaviour to being as was before
cs.selectAnnotation(annotation.id);
}
this.datamanager.invoke("annotationSet", annotation);
}
}
Expand Down
8 changes: 5 additions & 3 deletions web/libs/datamanager/src/stores/AppStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,14 +245,16 @@ export const AppStore = types

if (isFF(FF_REGION_VISIBILITY_FROM_URL)) {
const { annotation: annIDFromUrl, region: regionIDFromUrl } = History.getParams();
if (annIDFromUrl) {
const lsfAnnotation = self.LSF.lsf.annotationStore.annotations.find((a) => {
const annotationStore = self.LSF?.lsf?.annotationStore;

if (annIDFromUrl && annotationStore) {
const lsfAnnotation = [...annotationStore.annotations, ...annotationStore.predictions].find((a) => {
return a.pk === annIDFromUrl || a.id === annIDFromUrl;
});

if (lsfAnnotation) {
const annID = lsfAnnotation.pk ?? lsfAnnotation.id;
self.LSF?.setLSFTask(self.taskStore.selected, annID);
self.LSF?.setLSFTask(self.taskStore.selected, annID, undefined, lsfAnnotation.type === "prediction");
}
}
if (regionIDFromUrl) {
Expand Down
1 change: 1 addition & 0 deletions web/libs/editor/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ module.exports = {
"^react-konva-utils": "identity-obj-proxy",
"\\.(s[ac]ss|css|svg|png|jpe?g)$": "identity-obj-proxy",
"^@humansignal/ui": "<rootDir>/../ui/src/index.ts",
"^@humansignal/core/lib/(.*)$": "<rootDir>/../core/src/lib/$1",
},
testPathIgnorePatterns: ["/node_modules/", "/e2e/"],
testRegex: "__tests__/.*.test.[tj]sx?",
Expand Down
1 change: 1 addition & 0 deletions web/libs/editor/src/assets/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export { ReactComponent as IconCopy } from "./copy.svg";
export { ReactComponent as IconText } from "./text.svg";
export { ReactComponent as IconViewAll } from "./view-all.svg";
export { ReactComponent as IconLink } from "./link.svg";
export { ReactComponent as IconRelationLink } from "./link-relation.svg";
export { ReactComponent as IconPlusAlt } from "./plus-alt.svg";
export { ReactComponent as IconTrash } from "./trash.svg";
export { ReactComponent as IconTrashAlt } from "./trash-alt.svg";
Expand Down
7 changes: 7 additions & 0 deletions web/libs/editor/src/assets/icons/link-relation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions web/libs/editor/src/assets/icons/link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface DropdownProps {
className?: string;
dataTestId?: string;
style?: CSSProperties;
children?: JSX.Element;
children?: React.ReactNode;
onToggle?: (visible: boolean) => void;
}

Expand Down
4 changes: 2 additions & 2 deletions web/libs/editor/src/common/Dropdown/DropdownTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const getMinIndex = (element?: HTMLElement) => {

interface DropdownTriggerProps extends DropdownProps {
tag?: string;
dropdown?: RefObject<JSX.Element>;
content?: JSX.Element;
dropdown?: RefObject<DropdownRef>;
content?: React.ReactNode;
dataTestId?: string;
toggle?: boolean;
closeOnClickOutside?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
color: var(--sand_900);
}

& .annotation-button__ellipsisIcon {
& .annotation-button__trigger {
visibility: visible;
}
}
Expand All @@ -91,7 +91,7 @@
border-bottom-color: transparent;
}

& .annotation-button__ellipsisIcon {
& .annotation-button__trigger {
visibility: visible;
}

Expand Down Expand Up @@ -119,7 +119,7 @@
}
}

&__ellipsisIcon {
&__trigger {
transform: rotate(90deg);
display: flex;
border-radius: 4px;
Expand Down Expand Up @@ -166,70 +166,4 @@
}
}
}

&_contextMenuOpen {
& .annotation-button {
&__ellipsisIcon {
color: var(--grape_500);
background: var(--grape_0);
}
}
}
}

.AnnotationButtonContextMenu {
border-radius: 4px;
box-shadow: 0 1px 3px 1px #26262626, 0 1px 2px 0 #2626264D;

&__seperator {
height: 1px;
background-color: var(--sand_100);
}

&__option {
display: flex;
margin: 8px;
align-items: center;
white-space: nowrap;
gap: 2px;
cursor: pointer;
font-size: 14px;
font-weight: 400;
line-height: 22px;
border-radius: 4px;
padding-right: 32px;

&:hover {
background-color: var(--grape_0);
color: var(--grape_500);
}

&_duplicate {
padding-top: 6px;
padding-bottom: 6px;

.AnnotationButtonContextMenu__icon {
display: flex;
padding: 0 8px 0 9px;
align-items: center;
}
}

&_delete {
padding-top: 6px;
padding-bottom: 6px;
color: var(--danger_color);

&:hover {
background-color: var(--red_1);
color: var(--danger_color);
}

& .AnnotationButtonContextMenu__icon {
display: flex;
padding: 4px 11px 4px 12px;
align-items: center;
}
}
}
}
}
Loading
Loading