From 956249d5f1de21b8ab4b2e44726ea0ca09c8a8e2 Mon Sep 17 00:00:00 2001 From: Chris Beer Date: Wed, 16 Jun 2021 09:53:54 -0700 Subject: [PATCH 1/2] Increase the default stroke width for annotations, and allow applications to override that with some configuration --- __tests__/AnnotationCreation.test.js | 2 +- src/AnnotationCreation.js | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/__tests__/AnnotationCreation.test.js b/__tests__/AnnotationCreation.test.js index 5f79a82..d0a355d 100644 --- a/__tests__/AnnotationCreation.test.js +++ b/__tests__/AnnotationCreation.test.js @@ -10,7 +10,7 @@ function createWrapper(props) { return shallow( Date: Wed, 16 Jun 2021 14:36:57 -0700 Subject: [PATCH 2/2] Allow annotators to assign motivations to an annotation; fixes #57 --- __tests__/AnnotationCreation.test.js | 22 ++++++---- package.json | 3 ++ src/AnnotationCreation.js | 43 +++++++++++++++++-- src/WebAnnotation.js | 5 ++- .../annotationCreationCompanionWindow.js | 13 ++++++ 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/__tests__/AnnotationCreation.test.js b/__tests__/AnnotationCreation.test.js index d0a355d..698cc0c 100644 --- a/__tests__/AnnotationCreation.test.js +++ b/__tests__/AnnotationCreation.test.js @@ -1,5 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { I18nextProvider, initReactI18next } from 'react-i18next'; +import i18n from 'i18next'; import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup'; import AnnotationCreation from '../src/AnnotationCreation'; import AnnotationDrawing from '../src/AnnotationDrawing'; @@ -7,15 +9,19 @@ import TextEditor from '../src/TextEditor'; /** */ function createWrapper(props) { + const i18nconfig = i18n.createInstance(); + i18nconfig.use(initReactI18next).init({ lng: 'en', resources: {} }); return shallow( - , - ); + + + , + ).dive().dive().dive(); } describe('AnnotationCreation', () => { diff --git a/package.json b/package.json index 6b8f48c..d29dfbc 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "prop-types": "^15.7.2", "react": "^17.0", "react-dom": "^17.0", + "react-i18next": "^11.7.0", "uuid": "^8.0.0" }, "devDependencies": { @@ -62,6 +63,7 @@ "eslint-plugin-jsx-a11y": "^6.3.1", "eslint-plugin-react": "^7.20.3", "eslint-plugin-react-hooks": "^4.0.6", + "i18next": "^19.5.0", "jest": "^26.1.0", "jest-canvas-mock": "^2.2.0", "jest-localstorage-mock": "^2.4.2", @@ -70,6 +72,7 @@ "prop-types": "^15.7.2", "react": "^17.0", "react-dom": "^17.0", + "react-i18next": "^11.7.0", "uuid": "^8.2.0" }, "author": "", diff --git a/src/AnnotationCreation.js b/src/AnnotationCreation.js index 3ce88cf..1f03663 100644 --- a/src/AnnotationCreation.js +++ b/src/AnnotationCreation.js @@ -1,5 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import compose from 'lodash/flowRight'; +import { withTranslation } from 'react-i18next'; import Button from '@material-ui/core/Button'; import Typography from '@material-ui/core/Typography'; import Paper from '@material-ui/core/Paper'; @@ -22,6 +24,7 @@ import Divider from '@material-ui/core/Divider'; import MenuItem from '@material-ui/core/MenuItem'; import ClickAwayListener from '@material-ui/core/ClickAwayListener'; import MenuList from '@material-ui/core/MenuList'; +import Select from '@material-ui/core/Select'; import { SketchPicker } from 'react-color'; import { v4 as uuid } from 'uuid'; import { withStyles } from '@material-ui/core/styles'; @@ -63,6 +66,8 @@ class AnnotationCreation extends Component { annoState.svg = props.annotation.target.selector.value; } } + + annoState.motivation = props.annotation.motivation; } const toolState = { @@ -70,6 +75,7 @@ class AnnotationCreation extends Component { closedMode: 'closed', currentColorType: false, fillColor: null, + motivation: (props.config.annotation.motivations && props.config.annotation.motivations[0]), strokeColor: '#00BFFF', strokeWidth: 3, ...(props.config.annotation.defaults || {}), @@ -98,6 +104,7 @@ class AnnotationCreation extends Component { this.handleCloseLineWeight = this.handleCloseLineWeight.bind(this); this.closeChooseColor = this.closeChooseColor.bind(this); this.updateStrokeColor = this.updateStrokeColor.bind(this); + this.changeMotivation = this.changeMotivation.bind(this); } /** */ @@ -158,7 +165,7 @@ class AnnotationCreation extends Component { annotation, canvases, closeCompanionWindow, receiveAnnotation, config, } = this.props; const { - annoBody, tags, xywh, svg, + annoBody, tags, motivation, xywh, svg, } = this.state; canvases.forEach((canvas) => { const storageAdapter = config.annotation.adapter(canvas.id); @@ -167,6 +174,7 @@ class AnnotationCreation extends Component { canvasId: canvas.id, id: (annotation && annotation.id) || `${uuid()}`, manifestId: canvas.options.resource.id, + motivation, svg, tags, xywh, @@ -194,6 +202,13 @@ class AnnotationCreation extends Component { }); } + /** */ + changeMotivation(e) { + this.setState({ + motivation: e.target.value, + }); + } + /** */ changeClosedMode(e) { this.setState({ @@ -216,12 +231,13 @@ class AnnotationCreation extends Component { /** */ render() { const { - annotation, classes, closeCompanionWindow, id, windowId, + annotation, classes, closeCompanionWindow, config, id, t, windowId, } = this.props; const { activeTool, colorPopoverOpen, currentColorType, fillColor, popoverAnchorEl, strokeColor, popoverLineWeightAnchorEl, lineWeightPopoverOpen, strokeWidth, closedMode, annoBody, svg, + motivation, } = this.state; return (
+ { config.annotation + && config.annotation.motivations + && config.annotation.motivations.length > 0 && ( + <> + + + Motivation + + + + + + + )} Target @@ -435,10 +469,12 @@ AnnotationCreation.propTypes = { annotation: PropTypes.shape({ adapter: PropTypes.func, defaults: PropTypes.objectOf(PropTypes.string), + motivations: PropTypes.arrayOf(PropTypes.string), }), }).isRequired, id: PropTypes.string.isRequired, receiveAnnotation: PropTypes.func.isRequired, + t: PropTypes.func, windowId: PropTypes.string.isRequired, }; @@ -446,6 +482,7 @@ AnnotationCreation.defaultProps = { annotation: null, canvases: [], closeCompanionWindow: () => {}, + t: (k) => k, }; -export default withStyles(styles)(AnnotationCreation); +export default compose(withStyles(styles), withTranslation())(AnnotationCreation); diff --git a/src/WebAnnotation.js b/src/WebAnnotation.js index 22bff18..f9c6d4f 100644 --- a/src/WebAnnotation.js +++ b/src/WebAnnotation.js @@ -2,12 +2,13 @@ export default class WebAnnotation { /** */ constructor({ - canvasId, id, xywh, body, tags, svg, manifestId, + canvasId, id, xywh, body, tags, svg, manifestId, motivation = 'commenting', }) { this.id = id; this.canvasId = canvasId; this.xywh = xywh; this.body = body; + this.motivation = motivation; this.tags = tags; this.svg = svg; this.manifestId = manifestId; @@ -18,7 +19,7 @@ export default class WebAnnotation { return { body: this.createBody(), id: this.id, - motivation: 'commenting', + motivation: this.motivation, target: this.target(), type: 'Annotation', }; diff --git a/src/plugins/annotationCreationCompanionWindow.js b/src/plugins/annotationCreationCompanionWindow.js index 74937e6..db9002f 100644 --- a/src/plugins/annotationCreationCompanionWindow.js +++ b/src/plugins/annotationCreationCompanionWindow.js @@ -38,6 +38,19 @@ function mapStateToProps(state, { id: companionWindowId, windowId }) { export default { companionWindowKey: 'annotationCreation', component: AnnotationCreation, + config: { + annotation: { + motivations: ['commenting', 'describing', 'identifying', 'tagging'], + }, + translations: { + en: { + annotation_motivation_commenting: 'Commenting', + annotation_motivation_describing: 'Describing', + annotation_motivation_identifying: 'Identifying', + annotation_motivation_tagging: 'Tagging', + }, + }, + }, mapDispatchToProps, mapStateToProps, };