Skip to content

Commit

Permalink
Add the possibility to edit visual annotations
Browse files Browse the repository at this point in the history
Add the possibility to edit visual annotations
  • Loading branch information
TomDijkema committed Nov 6, 2024
1 parent 87cc838 commit 73f533b
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

.imagePopup {
min-width: 400px;
height: 150px;
max-height: 150px;
}
59 changes: 54 additions & 5 deletions src/components/elements/digitalMedia/ImagePopup.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/* Import Dependencies */
import { useSelection } from "@annotorious/react";
import { useAnnotator, useSelection, UserSelectAction } from "@annotorious/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from 'date-fns';
import { Formik, Form, Field } from "formik";
import KeycloakService from "app/Keycloak";
import { useRef } from "react";
import { Row, Col } from "react-bootstrap";

Expand All @@ -14,29 +16,39 @@ import { Annotation } from "app/types/Annotation";
/* Import Styles */
import styles from './DigitalMedia.module.scss';

/* Import Icons */
import { faPencil, faTrashCan } from "@fortawesome/free-solid-svg-icons";

/* Import Components */
import { Button, LoadingScreen } from "../customUI/CustomUI";


/* Props Type */
type Props = {
annotation?: Annotation,
editAnnotationWithId?: string,
loading: boolean,
SetAnnotoriousMode: Function,
SetEditAnnotationWithId: Function,
SubmitAnnotation: Function
};


/**
* Component that renders the image popup that appears when clicking on a visual annotation in the image viewer
* @param annotation The annotation to be represented in the popup
* @param editAnnotationWithId String holding the identifier of the annotation being annotated
* @param loading Boolean indicating if the loading state is active
* @param SetAnnotoriousMode Function to set the Annotorious mode
* @param SetEditAnnotationWithId Function to set the edit annotation with ID state
* @param SubmitAnnotation Function to submit the visual annotation
* @returns JSX Component
*/
const ImagePopup = (props: Props) => {
const { annotation, loading, SubmitAnnotation } = props;
const { annotation, editAnnotationWithId, loading, SetAnnotoriousMode, SetEditAnnotationWithId, SubmitAnnotation } = props;

/* Hooks */
const annotorious = useAnnotator();
const annotationValueFieldRef = useRef<HTMLInputElement>(null);
const trigger = useTrigger();

Expand All @@ -46,7 +58,7 @@ const ImagePopup = (props: Props) => {
const initialFormValues: {
annotationValue: string
} = {
annotationValue: ''
annotationValue: annotation ? annotation["oa:hasBody"]["oa:value"][0] : ''
};
let userTag: string = annotation?.['dcterms:creator']['schema:name'] ?? annotation?.['dcterms:creator']['@id'] ?? '';

Expand All @@ -60,7 +72,7 @@ const ImagePopup = (props: Props) => {
return (
<div className={`${styles.imagePopup} position-relative px-4 pt-2 pb-3 bgc-white b-grey br-corner box-shadow overflow-hidden`}>
{/* If annotation does not exist or is being edited, show form */}
{!isExistingAnnotation ?
{(!isExistingAnnotation || editAnnotationWithId) ?
<Formik initialValues={initialFormValues}
onSubmit={async (values) => {
await new Promise((resolve) => setTimeout(resolve, 100));
Expand All @@ -73,7 +85,7 @@ const ImagePopup = (props: Props) => {
<Row>
<Col>
<p className="tc-primary fw-bold">
New annotation
{`${!editAnnotationWithId ? 'New' : 'Edit'} annotation`}
</p>
</Col>
</Row>
Expand All @@ -93,6 +105,14 @@ const ImagePopup = (props: Props) => {
<Col>
<Button type="button"
variant="grey"
OnClick={() => {
if (editAnnotationWithId) {
SetEditAnnotationWithId(undefined);
} else {
annotorious.cancelSelected();
SetAnnotoriousMode('move');
}
}}
>
<p>Cancel</p>
</Button>
Expand Down Expand Up @@ -138,6 +158,35 @@ const ImagePopup = (props: Props) => {
</p>
</Col>
</Row>
{/* If annotation belongs to user, show options to edit or delete the annotation */}
{KeycloakService.GetParsedToken()?.orcid === annotation["dcterms:creator"]["@id"]}
<Row className="flex-row-reverse">
<Col lg="auto"
className="ps-0"
>
<Button type="button"
variant="blank"
className="px-0 py-0"
>
<FontAwesomeIcon icon={faTrashCan}
className="tc-primary"
/>
</Button>
</Col>
<Col lg="auto">
<Button type="button"
variant="blank"
className="px-0 py-0"
OnClick={() => {
SetEditAnnotationWithId(annotation["ods:ID"]);
}}
>
<FontAwesomeIcon icon={faPencil}
className="tc-primary"
/>
</Button>
</Col>
</Row>
</div>
}
</>
Expand Down
35 changes: 32 additions & 3 deletions src/components/elements/digitalMedia/ImageViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-nocheck

/* Import Dependencies */
import { OpenSeadragonAnnotator, OpenSeadragonAnnotationPopup, OpenSeadragonViewer, W3CImageAnnotation, W3CImageFormat, useAnnotator } from '@annotorious/react';
import { OpenSeadragonAnnotator, OpenSeadragonAnnotationPopup, OpenSeadragonViewer, UserSelectAction, W3CImageAnnotation, W3CImageFormat, useAnnotator } from '@annotorious/react';
import { useState } from 'react';

/* Import Utilities */
Expand All @@ -17,6 +17,7 @@ import { Dict } from 'app/Types';

/* Import API */
import InsertAnnotation from 'api/annotation/InsertAnnotation';
import PatchAnnotation from 'api/annotation/PatchAnnotation';

/* Import Components */
import ImagePopup from './ImagePopup';
Expand Down Expand Up @@ -53,6 +54,7 @@ const ImageViewer = (props: Props) => {
/* Base variables */
const [annotations, setAnnotations] = useState<Annotation[]>([]);
const [osdOptions, setOsdOptions] = useState<OpenSeadragon.Options | undefined>();
const [editAnnotationWithId, setEditAnnotationWithId] = useState<string | undefined>();

/**
* Function to refresh the visual annotations on the canvas
Expand Down Expand Up @@ -169,14 +171,24 @@ const ImageViewer = (props: Props) => {
annotorious.removeAnnotation(annotation);
}
});

/* If Annotorious mode is draw, set to move and set user select action to SELECT */
if (annotorious.isDrawingEnabled()) {
SetAnnotoriousMode('move');
}

/* Disable edit mode */
if (!selectedAnnotations.length || (editAnnotationWithId && annotorious.getSelected()?.[0].id !== editAnnotationWithId)) {
setEditAnnotationWithId(undefined);
}
});
}

/* If Annotorious and OpenSeadragon are ready, apply annotations to canvas */
if (annotorious && osdOptions) {
annotorious.viewer.addHandler('open', () => RefreshAnnotations());
}
}, [annotorious]);
}, [annotorious, editAnnotationWithId]);

/**
* Function to submit a visual annotation
Expand Down Expand Up @@ -223,7 +235,13 @@ const ImageViewer = (props: Props) => {

/* Try to post annotation to the API, if succeeds disable draw mode and update Annotorious annotation with DiSSCo identifier, otherwise return and show message */
try {
const annotation = await InsertAnnotation({ newAnnotation });
const annotation = !editAnnotationWithId ? await InsertAnnotation({ newAnnotation }) : await PatchAnnotation({
annotationId: editAnnotationWithId,
updatedAnnotation: newAnnotation
});

/* Refresh annotations state */
await RefreshAnnotations();

/* Update Annotorious annotation source on canvas */
UpdateAnnotoriousAnnotation(
Expand Down Expand Up @@ -270,13 +288,21 @@ const ImageViewer = (props: Props) => {
fill: '#a1d8ca'
});

/**
* Function for defining the select action of the OpenSeadragon annotator
*/
const SelectAction = () => {

};

return (
<div className="h-100 position-relative">
{osdOptions ?
<OpenSeadragonAnnotator adapter={W3CImageFormat('https://iiif.bodleian.ox.ac.uk/iiif/image/af315e66-6a85-445b-9e26-012f729fc49c')}
drawingEnabled={annotoriousMode === 'draw'}
drawingMode='click'
tool="rectangle"
userSelectAction={UserSelectAction.SELECT}
style={openSeadragonAnnotatorStyle}
>
<OpenSeadragonViewer options={osdOptions}
Expand All @@ -285,7 +311,10 @@ const ImageViewer = (props: Props) => {

<OpenSeadragonAnnotationPopup popup={() => (
<ImagePopup annotation={annotations.find(annotation => annotation['ods:ID'] === annotorious.getSelected()?.[0].id)}
editAnnotationWithId={editAnnotationWithId}
loading={loading.loading}
SetAnnotoriousMode={SetAnnotoriousMode}
SetEditAnnotationWithId={setEditAnnotationWithId}
SubmitAnnotation={SubmitAnnotation}
/>
)}
Expand Down

0 comments on commit 73f533b

Please sign in to comment.